Add unit tests to cover date field imports
authorEileen McNaughton <emcnaughton@wikimedia.org>
Thu, 19 May 2022 06:23:37 +0000 (18:23 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Thu, 19 May 2022 07:53:05 +0000 (19:53 +1200)
CRM/Contact/Import/Parser/Contact.php
tests/phpunit/CRM/Contact/Import/Form/data/individual_dates_type1.csv [new file with mode: 0644]
tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php

index afbe76f890c6b97c2645b7e200244b1b7166cf27..8f5418f95a80d5e377bfff8bd61d7884d0cf5eeb 100644 (file)
@@ -120,14 +120,13 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
    * @param $customFieldID
    * @param array $customFields
    * @param array $params
-   * @param array $addressCustomFields
    * @param $value
    * @param string $key
    * @param $dateType
    *
    * @return ?string
    */
-  private function validateCustomField($customFieldID, array $customFields, array $params, array $addressCustomFields, $value, string $key, $dateType): ?string {
+  private function validateCustomField($customFieldID, array $customFields, array $params, $value, string $key, $dateType): ?string {
     if (!array_key_exists($customFieldID, $customFields)) {
       return ts('field ID');
     }
@@ -136,11 +135,6 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
       return $customFields[$customFieldID]['label'] . '::' . $customFields[$customFieldID]['groupTitle'];
     }
 
-    //For address custom fields, we do get actual custom field value as an inner array of
-    //values so need to modify
-    if (array_key_exists($customFieldID, $addressCustomFields)) {
-      $value = $value[0][$key];
-    }
     /* validate the data against the CF type */
 
     if ($value) {
@@ -148,15 +142,10 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
       $htmlType = $customFields[$customFieldID]['html_type'];
       $isSerialized = CRM_Core_BAO_CustomField::isSerialized($customFields[$customFieldID]);
       if ($dataType == 'Date') {
-        if (array_key_exists($customFieldID, $addressCustomFields) && CRM_Utils_Date::convertToDefaultDate($params[$key][0], $dateType, $key)) {
-          $value = $params[$key][0][$key];
-        }
-        elseif (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
-          $value = $params[$key];
-        }
-        else {
-          return $customFields[$customFieldID]['label'];
+        if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
+          return NULL;
         }
+        return $customFields[$customFieldID]['label'];
       }
       elseif ($dataType == 'Boolean') {
         if (CRM_Utils_String::strtoboolstr($value) === FALSE) {
@@ -1225,12 +1214,26 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
     }
 
     $addressCustomFields = CRM_Core_BAO_CustomField::getFields('Address');
-    $customFields = $customFields + $addressCustomFields;
+    $parser = new CRM_Contact_Import_Parser_Contact();
     foreach ($params as $key => $value) {
       if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
-        /* check if it's a valid custom field id */
-        $parser = new CRM_Contact_Import_Parser_Contact();
-        $errors[] = $parser->validateCustomField($customFieldID, $customFields, $params, $addressCustomFields, $value, $key, $dateType);
+        //For address custom fields, we do get actual custom field value as an inner array of
+        //values so need to modify
+        if (array_key_exists($customFieldID, $addressCustomFields)) {
+          $value = $value[0][$key];
+          $dataType = $addressCustomFields[$customFieldID]['data_type'];
+          if ($dataType === 'Date') {
+            $input = ['custom_' . $customFieldID => $value];
+          }
+          else {
+            $input = $params;
+          }
+          $errors[] = $parser->validateCustomField($customFieldID, $addressCustomFields, $input, $value, $key, $dateType);
+        }
+        else {
+          /* check if it's a valid custom field id */
+          $errors[] = $parser->validateCustomField($customFieldID, $customFields, $params, $value, $key, $dateType);
+        }
       }
       elseif (is_array($params[$key]) && isset($params[$key]["contact_type"])) {
         //CRM-5125
diff --git a/tests/phpunit/CRM/Contact/Import/Form/data/individual_dates_type1.csv b/tests/phpunit/CRM/Contact/Import/Form/data/individual_dates_type1.csv
new file mode 100644 (file)
index 0000000..f0e0ce1
--- /dev/null
@@ -0,0 +1,8 @@
+first_name,Last Name,Birth Date,Deceased Date,Custom Date One,Custom Date Two,Street Address,Type,expected
+Joe,1,2008-09-01,2008-09-01,2008-09-01,2008-09-01,10 Downing St,1,Valid
+Joe,2,20080901,20080901,20080901,20080901,11 Downing St,1,Valid
+Joe,3,2008-9-1 ,2008-9-1 ,2008-9-1 ,2008-9-1 ,12 Downing St,1,Valid
+Joe,3,2008-25-1 ,2008-9-1 ,2008-9-1 ,2008-9-1 ,12 Downing St,1,Invalid
+Joe,3,2008-9-1 ,2008-25-1 ,2008-9-1 ,2008-9-1 ,12 Downing St,1,Invalid
+Joe,3,2008-9-1 ,2008-9-1 ,2008-25-1 ,2008-9-1 ,12 Downing St,1,Invalid
+Joe,3,2008-9-1 ,2008-9-1 ,2008-9-1 ,2008-25-1 ,12 Downing St,1,Invalid
index b4d263bb6e729f23c8c77b30bf57429da9baadae..c0dae22d37cdb0fd300248329de1b168ce86f519 100644 (file)
@@ -14,6 +14,7 @@
  * File for the CRM_Contact_Imports_Parser_ContactTest class.
  */
 
+use Civi\Api4\Address;
 use Civi\Api4\Contact;
 use Civi\Api4\RelationshipType;
 use Civi\Api4\UserJob;
@@ -850,7 +851,7 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
    * Test the determination of whether a custom field is valid.
    */
   public function testCustomFieldValidation(): void {
-    $errorMessage = [];
+    $errorMessage = '';
     $customGroup = $this->customGroupCreate([
       'extends' => 'Contact',
       'title' => 'ABC',
@@ -860,7 +861,7 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
       'custom_' . $customField['id'] => 'Label1|Label2',
     ];
     CRM_Contact_Import_Parser_Contact::isErrorInCustomData($params, $errorMessage);
-    $this->assertEquals([], $errorMessage);
+    $this->assertEquals(NULL, $errorMessage);
   }
 
   /**
@@ -1037,6 +1038,40 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     $this->assertCount(8, $contacts);
   }
 
+  /**
+   * @throws \Civi\API\Exception\UnauthorizedException
+   * @throws \API_Exception
+   * @throws \CRM_Core_Exception
+   */
+  public function testValidateDateData(): void {
+    $addressCustomGroupID = $this->createCustomGroup(['extends' => 'Address', 'name' => 'Address']);
+    $contactCustomGroupID = $this->createCustomGroup(['extends' => 'Contact', 'name' => 'Contact']);
+    $addressCustomFieldID = $this->createDateCustomField(['custom_group_id' => $addressCustomGroupID])['id'];
+    $contactCustomFieldID = $this->createDateCustomField(['custom_group_id' => $contactCustomGroupID])['id'];
+    $csv = 'individual_dates_type1.csv';
+    $dateType = CRM_Core_Form_Date::DATE_yyyy_mm_dd;
+    $mapper = [
+      ['first_name'],
+      ['last_name'],
+      ['birth_date'],
+      ['deceased_date'],
+      ['custom_' . $contactCustomFieldID],
+      ['custom_' . $addressCustomFieldID, 1],
+      ['street_address', 1],
+      ['do_not_import'],
+    ];
+    // Date types should be picked up from submitted values but still some clean up to do.
+    CRM_Core_Session::singleton()->set('dateTypes', $dateType);
+    $this->validateMultiRowCsv($csv, $mapper, 'custom_' . $addressCustomFieldID, ['dateFormats' => $dateType]);
+    $fields = ['contact_id.birth_date', 'contact_id.deceased_date', 'contact_id.custom_' . $contactCustomFieldID, $addressCustomFieldID];
+    $contacts = Address::get()->addWhere('contact_id.first_name', '=', 'Joe')->setSelect($fields)->execute();
+    foreach ($contacts as $contact) {
+      foreach ($fields as $field) {
+        $this->assertEquals('2008-09-01', $contact[$field]);
+      }
+    }
+  }
+
   /**
    * Test that setting duplicate action to fill doesn't blow away data
    * that exists, but does fill in where it's empty.
@@ -1519,4 +1554,34 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     $form->postProcess();
   }
 
+  /**
+   * @param string $csv
+   * @param array $mapper
+   * @param string $field
+   * @param array $submittedValues
+   *   Values submitted in the form process.
+   *
+   * @throws \API_Exception
+   * @throws \CRM_Core_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  private function validateMultiRowCsv(string $csv, array $mapper, string $field, $submittedValues): void {
+    /* @var CRM_Import_DataSource_CSV $dataSource */
+    /* @var \CRM_Contact_Import_Parser_Contact $parser */
+    [$dataSource, $parser] = $this->getDataSourceAndParser($csv, $mapper, $submittedValues);
+    while ($values = $dataSource->getRow()) {
+      try {
+        $parser->validateValues(array_values($values));
+        if ($values['expected'] !== 'Valid') {
+          $this->fail($values[$field] . ' should not have been valid');
+        }
+      }
+      catch (CRM_Core_Exception $e) {
+        if ($values['expected'] !== 'Invalid') {
+          $this->fail($values[$field] . ' should have been valid');
+        }
+      }
+    }
+  }
+
 }