diff --git a/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/PropertiesBase.php b/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/PropertiesBase.php index 5340b4280ae5e83d6d42ea4f78a968f6f339ad85..72bdbdf721100e9b76570de2c6368f1256d0562e 100644 --- a/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/PropertiesBase.php +++ b/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/PropertiesBase.php @@ -2,6 +2,7 @@ namespace Drupal\salesforce_mapping\Plugin\SalesforceMappingField; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\TypedData\ComplexDataDefinitionInterface; @@ -90,11 +91,14 @@ abstract class PropertiesBase extends SalesforceMappingFieldPluginBase { ->objectDescribe($mapping->getSalesforceObjectType()); $field_definition = $describe->getField($this->config('salesforce_field')); if ($field_definition['type'] == 'multipicklist') { - $values = []; - foreach ($entity->get($this->config('drupal_field_value')) as $value) { - $values[] = $this->getStringValue($entity, $value); + $data = $this->getDataValue($entity, $this->config('drupal_field_value')); + if (!empty($data)) { + $strings = []; + foreach ($data as $item) { + $strings[] = $item->getString(); + } + return implode(';', $strings); } - return implode(';', $values); } else { return $this->getStringValue($entity, $this->config('drupal_field_value')); @@ -211,8 +215,30 @@ abstract class PropertiesBase extends SalesforceMappingFieldPluginBase { */ protected function getStringValue(EntityInterface $entity, $drupal_field_value) { try { - return $this->dataFetcher()->fetchDataByPropertyPath($entity->getTypedData(), $drupal_field_value) - ->getString(); + $data = $this->getDataValue($entity, $drupal_field_value); + return empty($data) ? NULL : $data->getString(); + } + catch (\Exception $e) { + return NULL; + } + } + + /** + * Another helper Method to check for and retrieve field data. + * + * Same as getStringValue(), but returns the typed data prior to stringifying. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to search the Typed Data for. + * @param string $drupal_field_value + * The Typed Data property to get. + * + * @return \Drupal\Core\TypedData\TypedDataInterface|NULL + * The array representation of the Typed Data property value. + */ + protected function getDataValue(EntityInterface $entity, $drupal_field_value) { + try { + return $this->dataFetcher()->fetchDataByPropertyPath($entity->getTypedData(), $drupal_field_value); } catch (\Exception $e) { return NULL; diff --git a/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/RelatedProperties.php b/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/RelatedProperties.php index 0742a65f22f7c8d0fcb9d759273d9eab6cd02e07..7538745d289d8461f538b7e0a6db94774d401e34 100644 --- a/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/RelatedProperties.php +++ b/modules/salesforce_mapping/src/Plugin/SalesforceMappingField/RelatedProperties.php @@ -51,7 +51,7 @@ class RelatedProperties extends SalesforceMappingFieldPluginBase { * {@inheritdoc} */ public function value(EntityInterface $entity, SalesforceMappingInterface $mapping) { - list($field_name, $referenced_field_name) = explode(':', $this->config('drupal_field_value'), 2); + [$field_name, $referenced_field_name] = explode(':', $this->config('drupal_field_value'), 2); // Since we're not setting hard restrictions around bundles/fields, we may // have a field that doesn't exist for the given bundle/entity. In that // case, calling get() on an entity with a non-existent field argument @@ -80,7 +80,9 @@ class RelatedProperties extends SalesforceMappingFieldPluginBase { if ($field_definition['type'] == 'multipicklist') { $values = []; foreach ($field as $ref_entity) { - $values[] = $ref_entity->entity->get($referenced_field_name)->value; + if (!$ref_entity->entity->get($referenced_field_name)->isEmpty()) { + $values[] = $ref_entity->entity->get($referenced_field_name)->value; + } } return implode(';', $values); } @@ -101,7 +103,7 @@ class RelatedProperties extends SalesforceMappingFieldPluginBase { $definition['config_dependencies']['config'] = []; $field_name = $this->config('drupal_field_value'); if (strpos($field_name, ':')) { - list($field_name, $dummy) = explode(':', $field_name, 2); + [$field_name, $dummy] = explode(':', $field_name, 2); } // Add reference field. if ($field = FieldConfig::loadByName($this->mapping->getDrupalEntityType(), $this->mapping->getDrupalBundle(), $field_name)) { diff --git a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.field.node.salesforce_mapping_test_content.field_salesforce_test_multi.yml b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.field.node.salesforce_mapping_test_content.field_salesforce_test_multi.yml new file mode 100644 index 0000000000000000000000000000000000000000..6ef71933d7a8c3a06aacf558f97a70142cff2c36 --- /dev/null +++ b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.field.node.salesforce_mapping_test_content.field_salesforce_test_multi.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_salesforce_test_multi + - node.type.salesforce_mapping_test_content + module: + - options +id: node.salesforce_mapping_test_content.field_salesforce_test_multi +field_name: field_salesforce_test_multi +entity_type: node +bundle: salesforce_mapping_test_content +label: 'Salesforce Test Multi' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: list_string diff --git a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.storage.node.field_salesforce_test_multi.yml b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.storage.node.field_salesforce_test_multi.yml new file mode 100644 index 0000000000000000000000000000000000000000..4a9a221fed76aef9ca095084bcc6d9753980d9d3 --- /dev/null +++ b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/field.storage.node.field_salesforce_test_multi.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + module: + - node + - options +id: node.field_salesforce_test_multi +field_name: field_salesforce_test_multi +entity_type: node +type: list_string +settings: + allowed_values: + - + value: 'Value 1' + label: 'Value 1' + - + value: 'Value 2' + label: 'Value 2' + - + value: 'Value 3' + label: 'Value 3' + allowed_values_function: '' +module: options +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/node.type.salesforce_mapping_test_content.yml b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/node.type.salesforce_mapping_test_content.yml index f9812274041bbeb19639b833d9af84298fd149af..64371fbc43a909755ba2460fd4e258279175044f 100644 --- a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/node.type.salesforce_mapping_test_content.yml +++ b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/node.type.salesforce_mapping_test_content.yml @@ -1,5 +1,6 @@ langcode: en status: true +dependencies: { } name: 'Salesforce Mapping Test Content Type' type: salesforce_mapping_test_content description: '' diff --git a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/salesforce_mapping.salesforce_mapping.test_mapping.yml b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/salesforce_mapping.salesforce_mapping.test_mapping.yml index 9bd338e040efce610292a102997801150e7964be..d6ea961140918513cc6a49d6e3a053b9891f8517 100644 --- a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/salesforce_mapping.salesforce_mapping.test_mapping.yml +++ b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/config/install/salesforce_mapping.salesforce_mapping.test_mapping.yml @@ -6,12 +6,15 @@ dependencies: - field.field.node.salesforce_mapping_test_content.field_salesforce_test_date - field.field.node.salesforce_mapping_test_content.field_salesforce_test_email - field.field.node.salesforce_mapping_test_content.field_salesforce_test_link + - field.field.node.salesforce_mapping_test_content.field_salesforce_test_multi - field.field.node.salesforce_mapping_test_content.field_salesforce_test_reference - field.storage.node.field_salesforce_test_link - field.storage.node.field_salesforce_test_reference - node.type.salesforce_mapping_test_content module: - link + - salesforce_pull + - salesforce_push id: test_mapping label: 'Test Mapping' weight: 0 @@ -38,49 +41,64 @@ field_mappings: drupal_field_value: 'SALESFORCE TEST' salesforce_field: FirstName direction: drupal_sf - id: 8 + description: '' + id: 0 - drupal_field_type: DrupalConstant drupal_field_value: title direction: sf_drupal + description: '' drupal_constant: 'SALESFORCE TEST' - id: 9 + id: 1 - drupal_field_type: properties drupal_field_value: field_salesforce_test_email salesforce_field: Email direction: sync - id: 10 + description: '' + id: 2 - drupal_field_type: properties - drupal_field_value: field_salesforce_test_date + drupal_field_value: field_salesforce_test_date.value salesforce_field: Birthdate direction: sync - id: 11 + description: '' + id: 3 - drupal_field_type: properties drupal_field_value: field_salesforce_test_bool salesforce_field: d5__Do_Not_Mail__c direction: sync - id: 12 + description: '' + id: 4 - drupal_field_type: properties_extended drupal_field_value: field_salesforce_test_link.uri salesforce_field: Description direction: sync - id: 13 + description: '' + id: 5 - drupal_field_type: RelatedIDs drupal_field_value: field_salesforce_test_reference salesforce_field: ReportsToId direction: sync - id: 14 + description: '' + id: 6 - drupal_field_type: record_type drupal_field_value: Contact_Type_1 salesforce_field: RecordTypeId direction: drupal_sf - id: 15 + description: '' + id: 7 + - + drupal_field_type: properties + drupal_field_value: field_salesforce_test_multi + salesforce_field: d5__Multipicklist_Test__c + direction: sync + description: '' + id: 8 push_limit: 0 push_retries: 3 push_frequency: 0 diff --git a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/salesforce_mapping_test.info.yml b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/salesforce_mapping_test.info.yml index d36ea1dacd89af277ea25650d6a30eece43ee58d..98c0948ccb9c8b7a519dfcda06d73e13a05c80c7 100644 --- a/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/salesforce_mapping_test.info.yml +++ b/modules/salesforce_mapping/tests/modules/salesforce_mapping_test/salesforce_mapping_test.info.yml @@ -7,6 +7,10 @@ dependencies: - datetime - link - node + - options + - user - salesforce_mapping + - salesforce_push + - salesforce_pull - salesforce_test_rest_client - taxonomy diff --git a/modules/salesforce_mapping/tests/src/Functional/PushParamsTest.php b/modules/salesforce_mapping/tests/src/Functional/PushParamsTest.php index 55eac14e4a19bb56009baf3118217203dae232ca..d5830c16e8d3fcac5ea5057e1fe56693549283b6 100644 --- a/modules/salesforce_mapping/tests/src/Functional/PushParamsTest.php +++ b/modules/salesforce_mapping/tests/src/Functional/PushParamsTest.php @@ -4,6 +4,7 @@ namespace Drupal\Tests\salesforce_mapping\Functional; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; +use Drupal\KernelTests\KernelTestBase; use Drupal\node\Entity\Node; use Drupal\salesforce_mapping\Entity\MappedObject; use Drupal\salesforce_mapping\Entity\SalesforceMapping; @@ -32,8 +33,12 @@ class PushParamsTest extends BrowserTestBase { */ protected static $modules = [ 'typed_data', + 'options', 'dynamic_entity_reference', + 'salesforce', 'salesforce_mapping', + 'salesforce_push', + 'salesforce_pull', 'salesforce_mapping_test', ]; @@ -54,12 +59,11 @@ class PushParamsTest extends BrowserTestBase { $entity1->save(); // Mapped Object to be used for RelatedIDs push params property. - $mappedObject = MappedObject::create([ - 'drupal_entity' => $entity1, - 'salesforce_mapping' => $mapping, - 'salesforce_id' => '0123456789ABCDEFGH', - 'salesforce_link' => NULL, - ]); + $mappedObject = \Drupal::entityTypeManager() + ->getStorage('salesforce_mapped_object') + ->loadByEntityAndMapping($entity1, $mapping); + + $mappedObject->set('salesforce_id', '0123456789ABCDEFGH'); $mappedObject->save(); // Entity 2 to be mapped to Salesforce. @@ -71,6 +75,7 @@ class PushParamsTest extends BrowserTestBase { 'field_salesforce_test_email' => 'test2@example.com', 'field_salesforce_test_link' => 'https://example.com', 'field_salesforce_test_reference' => $entity1, + 'field_salesforce_test_multi' => [['value' => 'Value 1'], ['value' => 'Value 2'], ['value' => 'Value 3']], ]); $entity2->save(); @@ -81,11 +86,12 @@ class PushParamsTest extends BrowserTestBase { $expected = [ 'FirstName' => 'SALESFORCE TEST', 'Email' => 'test2@example.com', - 'Birthdate' => $expectedDate->format(DateTime::ISO8601), + 'Birthdate' => $expectedDate->format('Y-m-d\TH:i:sO'), 'd5__Do_Not_Mail__c' => TRUE, 'ReportsToId' => '0123456789ABCDEFGH', 'RecordTypeId' => '012i0000001B15mAAC', 'Description' => 'https://example.com', + 'd5__Multipicklist_Test__c' => 'Value 1;Value 2;Value 3' ]; $actual = $pushParams->getParams(); ksort($actual); @@ -108,12 +114,11 @@ class PushParamsTest extends BrowserTestBase { $entity1->save(); // Mapped Object to be used for RelatedIDs push params property. - $mappedObject = MappedObject::create([ - 'drupal_entity' => $entity1, - 'salesforce_mapping' => $mapping, - 'salesforce_id' => '0123456789ABCDEFGH', - 'salesforce_link' => NULL, - ]); + $mappedObject = \Drupal::entityTypeManager() + ->getStorage('salesforce_mapped_object') + ->loadByEntityAndMapping($entity1, $mapping); + + $mappedObject->set('salesforce_id', '0123456789ABCDEFGH'); $mappedObject->save(); // Entity 2 to be mapped to Salesforce. @@ -125,6 +130,7 @@ class PushParamsTest extends BrowserTestBase { 'field_salesforce_test_email' => 'test2@example.com', 'field_salesforce_test_link' => 'https://example.com', 'field_salesforce_test_reference' => $entity1, + 'field_salesforce_test_multi' => ['Value 1', 'Value 2', 'Value 3'], ]); $entity2->save(); @@ -133,11 +139,12 @@ class PushParamsTest extends BrowserTestBase { $expected = [ 'FirstName' => 'SALESFORCE TEST', 'Email' => 'test2@example.com', - 'Birthdate' => '', + 'Birthdate' => null, 'd5__Do_Not_Mail__c' => TRUE, 'ReportsToId' => '0123456789ABCDEFGH', 'RecordTypeId' => '012i0000001B15mAAC', 'Description' => 'https://example.com', + 'd5__Multipicklist_Test__c' => 'Value 1;Value 2;Value 3' ]; $actual = $pushParams->getParams(); ksort($actual); diff --git a/src/Tests/objectDescribe.json b/src/Tests/objectDescribe.json index b6b0d4e268e1a86998f88e1fd33c53243ebc3efc..bb22337be248726fa979021e65572e788b0ed86a 100644 --- a/src/Tests/objectDescribe.json +++ b/src/Tests/objectDescribe.json @@ -4140,6 +4140,85 @@ "unique": false, "updateable": false, "writeRequiresMasterRead": false - } + }, + "d5__Multipicklist_Test__c": { + "aggregatable": true, + "autoNumber": false, + "byteLength": 4099, + "calculated": true, + "calculatedFormula": "", + "cascadeDelete": false, + "caseSensitive": false, + "compoundFieldName": null, + "controllerName": null, + "createable": true, + "custom": true, + "defaultValue": null, + "defaultValueFormula": null, + "defaultedOnCreate": false, + "dependentPicklist": false, + "deprecatedAndHidden": false, + "digits": 0, + "displayLocationInDecimal": false, + "encrypted": false, + "externalId": false, + "extraTypeInfo": null, + "filterable": true, + "filteredLookupInfo": null, + "groupable": false, + "highScaleNumber": false, + "htmlFormatted": false, + "idLookup": false, + "inlineHelpText": null, + "label": "Multipicklist Test", + "length": 4099, + "mask": null, + "maskType": null, + "name": "d5__Multipicklist_Test__c", + "nameField": false, + "namePointing": false, + "nillable": true, + "permissionable": true, + "picklistValues": [ + { + "active": true, + "defaultValue": false, + "label": "Value 1", + "validFor": null, + "value": "Value 1" + }, + { + "active": true, + "defaultValue": false, + "label": "Value 2", + "validFor": null, + "value": "Value 2" + }, + { + "active": true, + "defaultValue": false, + "label": "Value 3", + "validFor": null, + "value": "Value 3" + } + ], + "polymorphicForeignKey": false, + "precision": 0, + "queryByDistance": false, + "referenceTargetField": null, + "referenceTo": [], + "relationshipName": null, + "relationshipOrder": null, + "restrictedDelete": false, + "restrictedPicklist": false, + "scale": 0, + "searchPrefilterable": false, + "soapType": "xsd:string", + "sortable": true, + "type": "multipicklist", + "unique": false, + "updateable": true, + "writeRequiresMasterRead": false + } } } \ No newline at end of file