Add check to ensure all have a primary address, fix identified but in IM.add
authoreileen <emcnaughton@wikimedia.org>
Tue, 15 Sep 2020 23:48:49 +0000 (11:48 +1200)
committereileen <emcnaughton@wikimedia.org>
Wed, 16 Sep 2020 10:21:10 +0000 (22:21 +1200)
CRM/Core/BAO/IM.php
tests/phpunit/CRM/Export/BAO/ExportTest.php
tests/phpunit/CiviTest/CiviUnitTestCase.php

index 3a950122dd68a3318ee5871e4d9a112f5656c91e..cdab960f6553f147df16cd296c2d536dec763594 100644 (file)
@@ -24,9 +24,15 @@ class CRM_Core_BAO_IM extends CRM_Core_DAO_IM {
    * Create or update IM record.
    *
    * @param array $params
-   * @return CRM_Core_DAO_IM
+   *
+   * @return \CRM_Core_DAO|\CRM_Core_DAO_IM
+   * @throws \CRM_Core_Exception
+   * @throws \API_Exception
    */
   public static function add($params) {
+    if (empty($params['id']) || is_numeric($params['is_primary'] ?? NULL)) {
+      CRM_Core_BAO_Block::handlePrimary($params, __CLASS__);
+    }
     return self::writeRecord($params);
   }
 
index 3db128633f5b388d7c8a1d785f90bbfb851252b8..7d21e3cfc09d0206fee66aa2302f7f6b8d37ff6c 100644 (file)
@@ -47,6 +47,13 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
 
   protected $locationTypes = [];
 
+  /**
+   * Should location types be checked to ensure primary addresses are correctly assigned after each test.
+   *
+   * @var bool
+   */
+  protected $isLocationTypesOnPostAssert = TRUE;
+
   /**
    * Processor generated in test.
    *
index 0930fb4f1e50f38e59a6873bfc92841daf9ba0ac..e2b1b4d65ea3e3520b218c8595e01f1cf7e062b9 100644 (file)
@@ -144,6 +144,13 @@ class CiviUnitTestCase extends PHPUnit\Framework\TestCase {
    */
   protected $isValidateFinancialsOnPostAssert = FALSE;
 
+  /**
+   * Should location types be checked to ensure primary addresses are correctly assigned after each test.
+   *
+   * @var bool
+   */
+  protected $isLocationTypesOnPostAssert = FALSE;
+
   /**
    * Class used for hooks during tests.
    *
@@ -495,6 +502,9 @@ class CiviUnitTestCase extends PHPUnit\Framework\TestCase {
    * @throws \CRM_Core_Exception
    */
   protected function assertPostConditions() {
+    if ($this->isLocationTypesOnPostAssert) {
+      $this->assertLocationValidity();
+    }
     if (!$this->isValidateFinancialsOnPostAssert) {
       return;
     }
@@ -3662,8 +3672,117 @@ VALUES
       'activity_details' => '',
     ];
     $form = new CRM_Case_Form_Case();
-    $caseObj = $form->testSubmit($caseParams, "OpenCase", $loggedInUser, "standalone");
-    return $caseObj;
+    return $form->testSubmit($caseParams, 'OpenCase', $loggedInUser, 'standalone');
+  }
+
+  /**
+   * Validate that all location entities have exactly one primary.
+   *
+   * This query takes about 2 minutes on a DB with 10s of millions of contacts.
+   */
+  public function assertLocationValidity() {
+    $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT COUNT(*) FROM
+
+(SELECT a1.contact_id
+FROM civicrm_address a1
+  LEFT JOIN civicrm_address a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE
+  a1.is_primary = 1
+  AND a2.id IS NOT NULL
+  AND a1.contact_id IS NOT NULL
+UNION
+SELECT a1.contact_id
+FROM civicrm_address a1
+       LEFT JOIN civicrm_address a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE a1.is_primary = 0
+  AND a2.id IS NULL
+  AND a1.contact_id IS NOT NULL
+
+UNION
+
+SELECT a1.contact_id
+FROM civicrm_email a1
+       LEFT JOIN civicrm_email a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE
+    a1.is_primary = 1
+  AND a2.id IS NOT NULL
+  AND a1.contact_id IS NOT NULL
+UNION
+SELECT a1.contact_id
+FROM civicrm_email a1
+       LEFT JOIN civicrm_email a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE a1.is_primary = 0
+  AND a2.id IS NULL
+  AND a1.contact_id IS NOT NULL
+
+UNION
+
+SELECT a1.contact_id
+FROM civicrm_phone a1
+       LEFT JOIN civicrm_phone a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE
+    a1.is_primary = 1
+  AND a2.id IS NOT NULL
+  AND a1.contact_id IS NOT NULL
+UNION
+SELECT a1.contact_id
+FROM civicrm_phone a1
+       LEFT JOIN civicrm_phone a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE a1.is_primary = 0
+  AND a2.id IS NULL
+  AND a1.contact_id IS NOT NULL
+
+UNION
+
+SELECT a1.contact_id
+FROM civicrm_im a1
+       LEFT JOIN civicrm_im a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE
+    a1.is_primary = 1
+  AND a2.id IS NOT NULL
+  AND a1.contact_id IS NOT NULL
+UNION
+SELECT a1.contact_id
+FROM civicrm_im a1
+       LEFT JOIN civicrm_im a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE a1.is_primary = 0
+  AND a2.id IS NULL
+  AND a1.contact_id IS NOT NULL
+
+UNION
+
+SELECT a1.contact_id
+FROM civicrm_openid a1
+       LEFT JOIN civicrm_openid a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE (a1.is_primary = 1 AND a2.id IS NOT NULL)
+UNION
+
+SELECT a1.contact_id
+FROM civicrm_openid a1
+       LEFT JOIN civicrm_openid a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE
+    a1.is_primary = 1
+  AND a2.id IS NOT NULL
+  AND a1.contact_id IS NOT NULL
+UNION
+SELECT a1.contact_id
+FROM civicrm_openid a1
+       LEFT JOIN civicrm_openid a2 ON a1.id <> a2.id AND a2.is_primary = 1
+  AND a1.contact_id = a2.contact_id
+WHERE a1.is_primary = 0
+  AND a2.id IS NULL
+  AND a1.contact_id IS NOT NULL) as primary_descrepancies
+    '));
   }
 
 }