Master only import regression - fix contactSubType handling
authorEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 2 May 2022 20:44:22 +0000 (08:44 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 2 May 2022 23:52:20 +0000 (11:52 +1200)
I found that the fieldname for contactSubType was actually subType
so renamed to contactSubType & ensured the type was set before
metadata loading

CRM/Contact/Import/Form/DataSource.php
CRM/Contact/Import/Form/MapField.php
CRM/Contact/Import/Form/Preview.php
CRM/Contact/Import/MetadataTrait.php
CRM/Contact/Import/Parser/Contact.php
CRM/Import/Forms.php
CRM/Import/Parser.php
templates/CRM/Contact/Import/Form/DataSource.tpl
tests/phpunit/CRM/Contact/Import/Form/MapFieldTest.php
tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php

index b39b67401094b425a1a38909cef0d80429bff792..3934871bffe8fe5e91da7add5fc43dd448948194 100644 (file)
@@ -110,7 +110,7 @@ class CRM_Contact_Import_Form_DataSource extends CRM_Import_Forms {
     }
     $this->addRadio('contactType', ts('Contact Type'), $contactTypeOptions, [], NULL, FALSE, $contactTypeAttributes);
 
-    $this->addElement('select', 'subType', ts('Subtype'));
+    $this->addElement('select', 'contactSubType', ts('Subtype'));
     $this->addElement('select', 'dedupe_rule_id', ts('Dedupe Rule'));
 
     CRM_Core_Form_Date::buildAllowedDateFormats($this);
@@ -181,11 +181,21 @@ class CRM_Contact_Import_Form_DataSource extends CRM_Import_Forms {
     // Setup the params array
     $this->_params = $this->controller->exportValues($this->_name);
 
+    // @todo - this params are being set here because they were / possibly still
+    // are in some places being accessed by forms later in the flow
+    // ie CRM_Contact_Import_Form_MapField, CRM_Contact_Import_Form_Preview
+    // or CRM_Contact_Import_Form_Summary using `$this->get()
+    // which was the old way of saving values submitted on this form such that
+    // the other forms could access them. Now they should use
+    // `getSubmittedValue` or simply not get them if the only
+    // reason is to pass to the Parser which can itself
+    // call 'getSubmittedValue'
+    // Once the mentioned forms no longer call $this->get() all this 'setting'
+    // is obsolete.
     $storeParams = [
       'onDuplicate' => $this->getSubmittedValue('onDuplicate'),
       'dedupe' => $this->getSubmittedValue('dedupe_rule_id'),
       'contactType' => $this->getSubmittedValue('contactType'),
-      'contactSubType' => $this->getSubmittedValue('subType'),
       'dateFormats' => $this->getSubmittedValue('dateFormats'),
       'savedMapping' => $this->getSubmittedValue('savedMapping'),
     ];
index f26d9264eae2d2a38bf5d5b64f2d31f98d93f633..7e69bb72ae76f6e4fd6969c7a5f6ca84bdc765d5 100644 (file)
@@ -74,7 +74,7 @@ class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
   public function preProcess() {
     $this->_mapperFields = $this->getAvailableFields();
     $this->_importTableName = $this->get('importTableName');
-    $this->_contactSubType = $this->get('contactSubType');
+    $this->_contactSubType = $this->getSubmittedValue('contactSubType');
     //format custom field names, CRM-2676
     $contactType = $this->getContactType();
 
@@ -294,7 +294,7 @@ class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
     $processor->setFormName($formName);
     $processor->setMetadata($this->getContactImportMetadata());
     $processor->setContactTypeByConstant($this->getSubmittedValue('contactType'));
-    $processor->setContactSubType($this->get('contactSubType'));
+    $processor->setContactSubType($this->getSubmittedValue('contactSubType'));
 
     for ($i = 0; $i < $this->_columnCount; $i++) {
       $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);
index 24472868868cc87ad622ab693039eb0a9a4437b5..805bfd1376d2fae374cd515ae26b47b170e02e7f 100644 (file)
@@ -229,7 +229,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
       'mapper' => $this->controller->exportValue('MapField', 'mapper'),
       'mapFields' => $this->getAvailableFields(),
       'contactType' => $this->get('contactType'),
-      'contactSubType' => $this->get('contactSubType'),
+      'contactSubType' => $this->getSubmittedValue('contactSubType'),
       'primaryKeyName' => $this->get('primaryKeyName'),
       'statusFieldName' => $this->get('statusFieldName'),
       'statusID' => $this->get('statusID'),
index 9f6390725cc10e298d05d6855fbb1432ebdc3539..fc8d570484274cd190bb43f7df7e381d39768296 100644 (file)
@@ -103,13 +103,4 @@ trait CRM_Contact_Import_MetadataTrait {
     return CRM_Utils_Array::collect('title', $this->getContactImportMetadata());
   }
 
-  /**
-   * Get configured contact sub type.
-   *
-   * @return string
-   */
-  protected function getContactSubType() {
-    return $this->_contactSubType ?? NULL;
-  }
-
 }
index 5caa074b9fc2668dbb5df5550cca4626bc3de78a..61cf658133d5c22a8e58fe912d166e2ed18e76ac 100644 (file)
@@ -2577,8 +2577,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
     // Since $this->_contactType is still being called directly do a get call
     // here to make sure it is instantiated.
     $this->getContactType();
-
-    $this->_contactSubType = $contactSubType;
+    $this->getContactSubType();
 
     $this->init();
 
@@ -3043,6 +3042,17 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
    * @param int $mode
    */
   public function set($store, $mode = self::MODE_SUMMARY) {
+    // @todo - this params are being set here because they were / possibly still
+    // are in some places being accessed by forms later in the flow
+    // ie CRM_Contact_Import_Form_MapField, CRM_Contact_Import_Form_Preview
+    // or CRM_Contact_Import_Form_Summary using `$this->get()
+    // which was the old way of saving values submitted on this form such that
+    // the other forms could access them. Now they should use
+    // `getSubmittedValue` or simply not get them if the only
+    // reason is to pass to the Parser which can itself
+    // call 'getSubmittedValue'
+    // Once the mentioned forms no longer call $this->get() all this 'setting'
+    // is obsolete.
     $store->set('rowCount', $this->_rowCount);
     $store->set('fieldTypes', $this->getSelectTypes());
 
index 08cd4c19ca738d9dcffbecb1fba21800c48cbfc5..9375b636ddfdee31c7e077ea9d93690055247431 100644 (file)
@@ -315,6 +315,18 @@ class CRM_Import_Forms extends CRM_Core_Form {
     return $contactTypeMapping[$this->getSubmittedValue('contactType')];
   }
 
+  /**
+   * Get the contact sub type selected for the import (on the datasource form).
+   *
+   * @return string|null
+   *   e.g Staff.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  protected function getContactSubType(): ?string {
+    return $this->getSubmittedValue('contactSubType');
+  }
+
   /**
    * Create a user job to track the import.
    *
index 598b567b2c3b4d268f2f91f498d89b77d9161eef..b87ccae753be8672e9da13535cabf956915e1b90 100644 (file)
@@ -115,6 +115,20 @@ abstract class CRM_Import_Parser {
     return $this->_contactType;
   }
 
+  /**
+   * Get configured contact type.
+   *
+   * @return string|null
+   *
+   * @throws \API_Exception
+   */
+  public function getContactSubType() {
+    if (!$this->_contactSubType) {
+      $this->_contactSubType = $this->getSubmittedValue('contactSubType');
+    }
+    return $this->_contactSubType;
+  }
+
   /**
    * Total number of non empty lines
    * @var int
@@ -266,13 +280,24 @@ abstract class CRM_Import_Parser {
    * @var string
    */
   public $_contactType;
+
   /**
    * Contact sub-type
    *
-   * @var int
+   * @var int|null
    */
   public $_contactSubType;
 
+  /**
+   * @param int|null $contactSubType
+   *
+   * @return self
+   */
+  public function setContactSubType(?int $contactSubType): self {
+    $this->_contactSubType = $contactSubType;
+    return $this;
+  }
+
   /**
    * Class constructor.
    */
index 57b7ff515a06811cca0a9152c33d06e54dc6d84b..f69e2a764c5391dbf89b4de3bda12305cef1e455 100644 (file)
@@ -36,7 +36,7 @@
          <tr class="crm-import-datasource-form-block-contactType">
        <td class="label">{$form.contactType.label}</td>
              <td>{$form.contactType.html} {help id='contact-type'}&nbsp;&nbsp;&nbsp;
-               <span id="contact-subtype">{$form.subType.label}&nbsp;&nbsp;&nbsp;{$form.subType.html} {help id='contact-sub-type'}</span></td>
+               <span id="contact-subtype">{$form.contactSubType.label}&nbsp;&nbsp;&nbsp;{$form.contactSubType.html} {help id='contact-sub-type'}</span></td>
          </tr>
          <tr class="crm-import-datasource-form-block-onDuplicate">
              <td class="label">{$form.onDuplicate.label}</td>
 
                         success: function(subtype){
                                                    if ( subtype.length == 0 ) {
-                                                      cj("#subType").empty();
+                                                      cj("#contactSubType").empty();
                                                       cj("#contact-subtype").hide();
                                                    } else {
                                                        cj("#contact-subtype").show();
-                                                       cj("#subType").empty();
+                                                       cj("#contactSubType").empty();
 
-                                                       cj("#subType").append("<option value=''>- {/literal}{ts escape='js'}select{/ts}{literal} -</option>");
+                                                       cj("#contactSubType").append("<option value=''>- {/literal}{ts escape='js'}select{/ts}{literal} -</option>");
                                                        for ( var key in  subtype ) {
                                                            // stick these new options in the subtype select
-                                                           cj("#subType").append("<option value="+key+">"+subtype[key]+" </option>");
+                                                           cj("#contactSubType").append("<option value="+key+">"+subtype[key]+" </option>");
                                                        }
                                                    }
 
index 94920164c109c565b841de0f4601130b052df80e..c4e236b9ba4fa1ceb98578df93abaaa7b9762626 100644 (file)
@@ -145,6 +145,7 @@ class CRM_Contact_Import_Form_MapFieldTest extends CiviUnitTestCase {
     CRM_Core_DAO::executeQuery('CREATE TABLE IF NOT EXISTS civicrm_tmp_d_import_job_xxx (`nada` text, `first_name` text, `last_name` text, `address` text) ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci');
     $submittedValues = array_merge([
       'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
+      'contactSubType' => '',
       'dataSource' => 'CRM_Import_DataSource_SQL',
       'sqlQuery' => 'SELECT * FROM civicrm_tmp_d_import_job_xxx',
       'onDuplicate' => CRM_Import_Parser::DUPLICATE_UPDATE,
@@ -390,6 +391,16 @@ document.forms.MapField['mapper[0][3]'].style.display = 'none';\n",
     return $this->_contactType ?? 'Individual';
   }
 
+  /**
+   * This is accessed by virtue of the MetaDataTrait being included.
+   *
+   * The use of the metadataTrait came from a transitional refactor
+   * but it probably should be phased out again.
+   */
+  protected function getContactSubType(): string {
+    return $this->_contactSubType ?? '';
+  }
+
   /**
    * Wrapper for loadSavedMapping.
    *
index 0bd3695705a83a77320394ad59f4ac59017fa26e..8b6030c3b7dd4c39cf9abcbb3b05859749b4a5f9 100644 (file)
@@ -38,7 +38,7 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
    * @throws \CRM_Core_Exception
    */
   public function tearDown(): void {
-    $this->quickCleanup(['civicrm_address', 'civicrm_phone', 'civicrm_email'], TRUE);
+    $this->quickCleanup(['civicrm_address', 'civicrm_phone', 'civicrm_email', 'civicrm_user_job'], TRUE);
     parent::tearDown();
   }
 
@@ -59,7 +59,7 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     $fields = array_keys($contactImportValues);
     $values = array_values($contactImportValues);
     $parser = new CRM_Contact_Import_Parser_Contact($fields, []);
-    $parser->_contactType = 'Individual';
+    $parser->setUserJobID($this->getUserJobID());
     $parser->init();
     $this->mapRelationshipFields($fields, $parser->getAllFields());
 
@@ -70,22 +70,21 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     ], [
       NULL,
       NULL,
-      "Organization",
+      'Organization',
     ], [
       NULL,
       NULL,
-      "organization_name",
+      'organization_name',
     ], [], [], [], [], []);
-
-    $parser->_contactType = 'Individual';
+    $parser->setUserJobID($this->getUserJobID());
     $parser->_onDuplicate = CRM_Import_Parser::DUPLICATE_UPDATE;
     $parser->init();
 
     $this->assertEquals(CRM_Import_Parser::VALID, $parser->import(CRM_Import_Parser::DUPLICATE_UPDATE, $values), 'Return code from parser import was not as expected');
     $this->callAPISuccess("Contact", "get", [
-      "first_name"        => "Alok",
-      "last_name"         => "Patel",
-      "organization_name" => "Agileware",
+      'first_name' => 'Alok',
+      'last_name' => 'Patel',
+      'organization_name' => 'Agileware',
     ]);
   }
 
@@ -921,7 +920,7 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     }
     $values = array_values($originalValues);
     $parser = new CRM_Contact_Import_Parser_Contact($fields, $mapperLocType);
-    $parser->_contactType = 'Individual';
+    $parser->setUserJobID($this->getUserJobID());
     $parser->_dedupeRuleGroupID = $ruleGroupId;
     $parser->_onDuplicate = $onDuplicateAction;
     $parser->init();
@@ -967,15 +966,17 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
    * @throws \API_Exception
    * @throws \Civi\API\Exception\UnauthorizedException
    */
-  protected function getUserJobID() {
-    $userJobID = UserJob::create()->setValues([
+  protected function getUserJobID($submittedValues = []) {
+    return UserJob::create()->setValues([
       'metadata' => [
-        'submitted_values' => ['contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL],
+        'submitted_values' => array_merge([
+          'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
+          'contactSubType' => '',
+        ], $submittedValues),
       ],
       'status_id:name' => 'draft',
       'type_id:name' => 'contact_import',
     ])->execute()->first()['id'];
-    return $userJobID;
   }
 
 }