dev/core#2046 Fix blockDelete to delete while ensuring is_primary is valid
authoreileen <emcnaughton@wikimedia.org>
Fri, 2 Oct 2020 01:32:56 +0000 (14:32 +1300)
committereileen <emcnaughton@wikimedia.org>
Fri, 2 Oct 2020 01:32:56 +0000 (14:32 +1300)
The del function on each of the location DAO ensures that after a delete at least one phone (etc) is
marked is_primary. This blockDelete does not do that & per the test it's possible to call this
in such a way that no addresses are primary. Whether this actually happens is a bit unknown.

However, this cleans up block delete in a way where we can demonstrate the tests work

CRM/Core/BAO/Block.php
tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php

index 898b88360a27c48cabb8b07922403a18a0e29beb..10cff14b3f49524ea2043cc69382c0858fe135d7 100644 (file)
@@ -337,15 +337,8 @@ class CRM_Core_BAO_Block {
       $name = 'OpenID';
     }
 
-    $baoString = 'CRM_Core_DAO_' . $name;
-    $block = new $baoString();
-
-    $block->copyValues($params);
-
-    // CRM-11006 add call to pre and post hook for delete action
-    CRM_Utils_Hook::pre('delete', $name, $block->id, CRM_Core_DAO::$_nullArray);
-    $block->delete();
-    CRM_Utils_Hook::post('delete', $name, $block->id, $block);
+    $baoString = 'CRM_Core_BAO_' . $name;
+    $baoString::del($params['id']);
   }
 
   /**
index d6e4ea58a2d2883f3a0d0566480fbe45eab507cc..fbfa8f9990b087ba8c9ffc844eddbb21aab2e5fc 100644 (file)
@@ -255,6 +255,94 @@ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase {
     $this->callAPISuccess('Contact', 'delete', ['id' => $contact['id']]);
   }
 
+  /**
+   * Test that the not-really-encouraged way of creating locations via contact.create doesn't mess up primaries.
+   */
+  public function testContactLocationBlockHandling() {
+    $id = $this->individualCreate([
+      'phone' => [
+        1 => [
+          'location_type_id' => 1,
+          'phone' => '987654321',
+        ],
+        2 => [
+          'location_type_id' => 2,
+          'phone' => '456-7890',
+        ],
+      ],
+      'im' => [
+        1 => [
+          'location_type_id' => 1,
+          'name' => 'bob',
+        ],
+        2 => [
+          'location_type_id' => 2,
+          'name' => 'fred',
+        ],
+      ],
+      'openid' => [
+        1 => [
+          'location_type_id' => 1,
+          'openid' => 'bob',
+        ],
+        2 => [
+          'location_type_id' => 2,
+          'openid' => 'fred',
+        ],
+      ],
+      'email' => [
+        1 => [
+          'location_type_id' => 1,
+          'email' => 'bob@example.com',
+        ],
+        2 => [
+          'location_type_id' => 2,
+          'email' => 'fred@example.com',
+        ],
+      ],
+    ]);
+    $phones = $this->callAPISuccess('Phone', 'get', ['contact_id' => $id])['values'];
+    $emails = $this->callAPISuccess('Email', 'get', ['contact_id' => $id])['values'];
+    $openIDs = $this->callAPISuccess('OpenID', 'get', ['contact_id' => $id])['values'];
+    $ims = $this->callAPISuccess('IM', 'get', ['contact_id' => $id])['values'];
+    $this->assertCount(2, $phones);
+    $this->assertCount(2, $emails);
+    $this->assertCount(2, $ims);
+    $this->assertCount(2, $openIDs);
+
+    $this->assertLocationValidity();
+    $this->callAPISuccess('Contact', 'create', [
+      'id' => $id,
+      // This is secret code for 'delete this phone'.
+      'updateBlankLocInfo' => TRUE,
+      'phone' => [
+        1 => [
+          'id' => key($phones),
+        ],
+      ],
+      'email' => [
+        1 => [
+          'id' => key($emails),
+        ],
+      ],
+      'im' => [
+        1 => [
+          'id' => key($ims),
+        ],
+      ],
+      'openid' => [
+        1 => [
+          'id' => key($openIDs),
+        ],
+      ],
+    ]);
+    $this->assertLocationValidity();
+    $this->callAPISuccessGetCount('Phone', ['contact_id' => $id], 1);
+    $this->callAPISuccessGetCount('Email', ['contact_id' => $id], 1);
+    $this->callAPISuccessGetCount('OpenID', ['contact_id' => $id], 1);
+    $this->callAPISuccessGetCount('IM', ['contact_id' => $id], 1);
+  }
+
   /**
    * Test that the import parser adds the address to the primary location.
    *