Fix Contact.create calls to respect passed in variables & variables set via hook...
authoreileen <emcnaughton@wikimedia.org>
Wed, 20 Mar 2019 01:28:59 +0000 (14:28 +1300)
committereileen <emcnaughton@wikimedia.org>
Wed, 20 Mar 2019 05:28:50 +0000 (18:28 +1300)
This has been applied to Organizations & Households, not Individuals at this stage as that is more complex.

Use case is saving organizations with The so that The is at the end of their sort_name, making it easier to
deal with data entry variations

CRM/Contact/BAO/Contact.php
api/v3/Generic/Update.php
tests/phpunit/api/v3/ContactTest.php

index cea1e9da86aac4c905453c2ea4dd96c1d3ef4753..ed8ad48573aadb89f5d43252b70f6a37662e5d44 100644 (file)
@@ -146,39 +146,35 @@ class CRM_Contact_BAO_Contact extends CRM_Contact_DAO_Contact {
       $params['contact_sub_type'] = 'null';
     }
 
-    // Fixed contact source.
-    if (isset($params['contact_source'])) {
-      $params['source'] = $params['contact_source'];
-    }
-
     if (isset($params['preferred_communication_method']) && is_array($params['preferred_communication_method'])) {
       CRM_Utils_Array::formatArrayKeys($params['preferred_communication_method']);
       $contact->preferred_communication_method = CRM_Utils_Array::implodePadded($params['preferred_communication_method']);
       unset($params['preferred_communication_method']);
     }
 
+    $defaults = ['source' => CRM_Utils_Array::value('contact_source', $params)];
+    if ($params['contact_type'] === 'Organization' && isset($params['organization_name'])) {
+      $defaults['display_name'] = $params['organization_name'];
+      $defaults['sort_name'] = $params['organization_name'];
+    }
+    if ($params['contact_type'] === 'Household' && isset($params['household_name'])) {
+      $defaults['display_name'] = $params['household_name'];
+      $defaults['sort_name'] = $params['household_name'];
+    }
+    $params = array_merge($defaults, $params);
+
     $allNull = $contact->copyValues($params);
 
     $contact->id = CRM_Utils_Array::value('contact_id', $params);
 
     if ($contact->contact_type == 'Individual') {
       $allNull = FALSE;
-
+      // @todo allow the lines below to be overridden by input or hooks & add tests,
+      // as has been done for households and organizations.
       // Format individual fields.
       CRM_Contact_BAO_Individual::format($params, $contact);
     }
-    elseif ($contact->contact_type == 'Household') {
-      if (isset($params['household_name'])) {
-        $allNull = FALSE;
-        $contact->display_name = $contact->sort_name = CRM_Utils_Array::value('household_name', $params, '');
-      }
-    }
-    elseif ($contact->contact_type == 'Organization') {
-      if (isset($params['organization_name'])) {
-        $allNull = FALSE;
-        $contact->display_name = $contact->sort_name = CRM_Utils_Array::value('organization_name', $params, '');
-      }
-    }
+
     if (strlen($contact->display_name) > 128) {
       $contact->display_name = substr($contact->display_name, 0, 128);
     }
index d982f0742659bb9fa5b4540417e4006ffddc3152..0ba2aafb29fa7cad3596c651d64c452e5f53debd 100644 (file)
@@ -77,6 +77,12 @@ function civicrm_api3_generic_update($apiRequest) {
   }
 
   $existing = array_pop($existing['values']);
+  // Per Unit test testUpdateHouseholdWithAll we don't want to load these from the DB
+  // if they are not passed in then we'd rather they are calculated.
+  // Note update is not recomended anyway...
+  foreach (['sort_name', 'display_name'] as $fieldToNotSet) {
+    unset($existing[$fieldToNotSet]);
+  }
   $p = array_merge($existing, $apiRequest['params']);
   return civicrm_api($apiRequest['entity'], 'create', $p);
 }
index db06ecd190094f8a81dfa83d20f93362f22baadb..a4277293822989f4b2cbf771af8b93396ce5c0bb 100644 (file)
@@ -2532,6 +2532,38 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['sort_name']);
   }
 
+  /**
+   * Test that we can set the sort name via the api or alter it via a hook.
+   *
+   * As of writing this is being fixed for Organization & Household but it makes sense to do for individuals too.
+   */
+  public function testCreateAlterSortName() {
+    $organizationID = $this->organizationCreate(['organization_name' => 'The Justice League', 'sort_name' => 'Justice League, The']);
+    $organization = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name'], 'id' => $organizationID]);
+    $this->assertEquals('Justice League, The', $organization['sort_name']);
+    $this->assertEquals('The Justice League', $organization['display_name']);
+    $this->hookClass->setHook('civicrm_pre', array($this, 'killTheJusticeLeague'));
+    $this->organizationCreate(['id' => $organizationID, 'sort_name' => 'Justice League, The']);
+    $organization = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name', 'is_deceased'], 'id' => $organizationID]);
+    $this->assertEquals('Steppenwolf wuz here', $organization['display_name']);
+    $this->assertEquals('Steppenwolf wuz here', $organization['sort_name']);
+    $this->assertEquals(1, $organization['is_deceased']);
+
+    $householdID = $this->householdCreate();
+    $household = $this->callAPISuccessGetSingle('Contact', ['return' => ['sort_name', 'display_name'], 'id' => $householdID]);
+    $this->assertEquals('Steppenwolf wuz here', $household['display_name']);
+    $this->assertEquals('Steppenwolf wuz here', $household['sort_name']);
+  }
+
+  /**
+   * Implements hook_pre().
+   */
+  public function killTheJusticeLeague($op, $entity, $id, &$params) {
+    $params['sort_name'] = 'Steppenwolf wuz here';
+    $params['display_name'] = 'Steppenwolf wuz here';
+    $params['is_deceased'] = 1;
+  }
+
   /**
    * Test Single Entity format.
    */