Validate subtype change
authorEileen McNaughton <emcnaughton@wikimedia.org>
Tue, 17 May 2022 23:09:33 +0000 (11:09 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Wed, 18 May 2022 20:20:09 +0000 (08:20 +1200)
CRM/Contact/Import/Parser/Contact.php
tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php

index 7420b956490b103bafe85bc45d2057ae4ae1c225..00ae15f24f628bde104eaa1048e34490a9baba94 100644 (file)
@@ -300,28 +300,26 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
 
     $params = $this->getMappedRow($values);
     $formatted = [
-      'contact_type' => $this->_contactType,
+      'contact_type' => $this->getContactType(),
     ];
 
     $contactFields = CRM_Contact_DAO_Contact::import();
 
-    if (!empty($this->_contactSubType)) {
-      $params['contact_sub_type'] = $this->_contactSubType;
-    }
+    $params['contact_sub_type'] = $this->getContactSubType() ?: ($params['contact_sub_type'] ?? NULL);
 
-    if ($subType = CRM_Utils_Array::value('contact_sub_type', $params)) {
-      if (CRM_Contact_BAO_ContactType::isExtendsContactType($subType, $this->_contactType, FALSE, 'label')) {
-        $subTypes = CRM_Contact_BAO_ContactType::subTypePairs($this->_contactType, FALSE, NULL);
-        $params['contact_sub_type'] = array_search($subType, $subTypes);
-      }
-      elseif (!CRM_Contact_BAO_ContactType::isExtendsContactType($subType, $this->_contactType)) {
-        $message = "Mismatched or Invalid Contact Subtype.";
-        array_unshift($values, $message);
-        return CRM_Import_Parser::NO_MATCH;
+    if ($params['contact_sub_type']) {
+      if (CRM_Contact_BAO_ContactType::isExtendsContactType($params['contact_sub_type'], $this->getContactType(), FALSE, 'label')) {
+        // I think this bit is switching a passed in label to
+        // a name.
+        $subTypes = CRM_Contact_BAO_ContactType::subTypePairs($this->getContactType(), FALSE, NULL);
+        $params['contact_sub_type'] = array_search($params['contact_sub_type'], $subTypes);
       }
     }
 
     try {
+      if ($params['contact_sub_type'] && !CRM_Contact_BAO_ContactType::isExtendsContactType($params['contact_sub_type'], $this->getContactType())) {
+        throw new CRM_Core_Exception('Mismatched or Invalid Contact Subtype.', CRM_Import_Parser::NO_MATCH);
+      }
       $params['id'] = $formatted['id'] = $this->lookupContactID($params, ($this->isSkipDuplicates() || $this->isIgnoreDuplicates()));
     }
     catch (CRM_Core_Exception $e) {
index 347cf2c47f4ff0aa1a1c94c81225ce0b3fb2684b..b4d263bb6e729f23c8c77b30bf57429da9baadae 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 use Civi\Api4\Contact;
+use Civi\Api4\RelationshipType;
 use Civi\Api4\UserJob;
 
 /**
@@ -37,7 +38,8 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
    * Tear down after test.
    */
   public function tearDown(): void {
-    $this->quickCleanup(['civicrm_address', 'civicrm_phone', 'civicrm_email', 'civicrm_user_job'], TRUE);
+    $this->quickCleanup(['civicrm_address', 'civicrm_phone', 'civicrm_email', 'civicrm_user_job', 'civicrm_relationship'], TRUE);
+    RelationshipType::delete()->addWhere('name_a_b', '=', 'Dad to')->execute();
     parent::tearDown();
   }
 
@@ -250,9 +252,11 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
   /**
    * Test updating an existing contact with external_identifier match but subtype mismatch.
    *
+   * The subtype is updated, as there is no conflicting contact data.
+   *
    * @throws \Exception
    */
-  public function testImportParserWithUpdateWithExternalIdentifierSubtypeMismatch(): void {
+  public function testImportParserWithUpdateWithExternalIdentifierSubtypeChange(): void {
     $contactID = $this->individualCreate(['external_identifier' => 'billy', 'first_name' => 'William', 'contact_sub_type' => 'Parent']);
     $this->runImport([
       'external_identifier' => 'billy',
@@ -1286,6 +1290,28 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     return [$dataSource, $parser];
   }
 
+  /**
+   * @param int $contactID
+   *
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  protected function addChild(int $contactID): void {
+    $relatedContactID = $this->individualCreate();
+    $relationshipTypeID = RelationshipType::create()->setValues([
+      'name_a_b' => 'Dad to',
+      'name_b_a' => 'Sleep destroyer of',
+      'contact_type_a' => 'Individual',
+      'contact_type_b' => 'Individual',
+      'contact_sub_type_a' => 'Parent',
+    ])->execute()->first()['id'];
+    \Civi\Api4\Relationship::create()->setValues([
+      'relationship_type_id' => $relationshipTypeID,
+      'contact_id_a' => $contactID,
+      'contact_id_b' => $relatedContactID,
+    ])->execute();
+  }
+
   /**
    * @param array $fields Array of fields to be imported
    * @param array $allfields Array of all fields which can be part of import