CRM-14478 - Add CRM_Core_DAO::getReferenceCounts()
authorTim Otten <totten@civicrm.org>
Wed, 21 May 2014 08:34:56 +0000 (01:34 -0700)
committerTim Otten <totten@civicrm.org>
Fri, 23 May 2014 03:40:25 +0000 (20:40 -0700)
CRM/Core/DAO.php
CRM/Core/Reference/Basic.php
CRM/Core/Reference/Dynamic.php
CRM/Core/Reference/Interface.php
CRM/Core/Reference/OptionValue.php
tests/phpunit/CRM/Core/DAOTest.php

index cceb90211f835bc19738c489ee2816457b7d30c4..b475f23b283be6128e396964e0bcdb57bd480329 100644 (file)
@@ -1779,6 +1779,21 @@ SELECT contact_id
     return $occurrences;
   }
 
+  function getReferenceCounts() {
+    $links = self::getReferencesToTable(static::getTableName());
+
+    $counts = array();
+    foreach ($links as $refSpec) {
+      /** @var $refSpec CRM_Core_Reference_Interface */
+      $count = $refSpec->getReferenceCount($this);
+      if ($count['count'] != 0) {
+        $counts[] = $count;
+      }
+    }
+
+    return $counts;
+  }
+
   /**
    * List all tables which have hard foreign keys to this table.
    *
index f72a664bd7c72dd197867ddc67e606441c323ead..f0c897e268e5ec5b79b66869b63f9120f8e0b69d 100644 (file)
@@ -59,4 +59,24 @@ EOS;
     $result = CRM_Core_DAO::executeQuery($sql, $params, TRUE, $daoName);
     return $result;
   }
+
+  public function getReferenceCount($targetDao) {
+    $targetColumn = $this->getTargetKey();
+    $params = array(
+      1 => array($targetDao->$targetColumn, 'String')
+    );
+    $sql = <<<EOS
+SELECT count(id)
+FROM {$this->getReferenceTable()}
+WHERE {$this->getReferenceKey()} = %1
+EOS;
+
+    return array(
+      'name' => implode(':', array('sql', $this->getReferenceTable(), $this->getReferenceKey())),
+      'type' => get_class($this),
+      'table' => $this->getReferenceTable(),
+      'key' => $this->getReferenceKey(),
+      'count' => CRM_Core_DAO::singleValueQuery($sql, $params)
+    );
+  }
 }
index fdcf77546fde931fc0714d6a16a6a4c82ac1a7f0..85c5d00f334e8f646a86dd2c070a0869de1ae94d 100644 (file)
@@ -40,4 +40,31 @@ EOS;
     $result = CRM_Core_DAO::executeQuery($sql, $params, TRUE, $daoName);
     return $result;
   }
+
+  public function getReferenceCount($targetDao) {
+    $targetColumn = $this->getTargetKey();
+    $params = array(
+      1 => array($targetDao->$targetColumn, 'String'),
+
+      // If anyone complains about $targetDao::getTableName(), then could use
+      // "{get_class($targetDao)}::getTableName();"
+      2 => array($targetDao::getTableName(), 'String'),
+    );
+
+    $sql = <<<EOS
+SELECT count(id)
+FROM {$this->getReferenceTable()}
+WHERE {$this->getReferenceKey()} = %1
+AND {$this->getTypeColumn()} = %2
+EOS;
+
+    return array(
+      'name' => implode(':', array('sql', $this->getReferenceTable(), $this->getReferenceKey())),
+      'type' => get_class($this),
+      'table' => $this->getReferenceTable(),
+      'key' => $this->getReferenceKey(),
+      'count' => CRM_Core_DAO::singleValueQuery($sql, $params)
+    );
+  }
+
 }
index f949994c3b11b82d9bbf0233f895b343f8c79962..e4cb7e5ecb5dc7dbec660bb4d6e28f720e913ef7 100644 (file)
@@ -19,4 +19,14 @@ interface CRM_Core_Reference_Interface {
    * @return CRM_Core_DAO|NULL a query-handle (like the result of CRM_Core_DAO::executeQuery)
    */
   public function findReferences($targetDao);
+
+  /**
+   * Create a query to find references to a particular record
+   *
+   * @param CRM_Core_DAO $targetDao the instance for which we want references
+   * @return array a record describing the reference; must include the keys:
+   *  - 'type': string (not necessarily unique)
+   *  - 'count': int
+   */
+  public function getReferenceCount($targetDao);
 }
index 7c97972afc995f28ca760597ce833cab8fa01065..6c983ba337f5252b62cbb19e21ce6ec180819318 100644 (file)
@@ -30,6 +30,17 @@ class CRM_Core_Reference_OptionValue extends CRM_Core_Reference_Basic {
     }
   }
 
+  public function getReferenceCount($targetDao) {
+    if (! ($targetDao instanceof CRM_Core_DAO_OptionValue)) {
+      throw new CRM_Core_Exception("Mismatched reference: expected OptionValue but received " . get_class($targetDao));
+    }
+    if ($targetDao->option_group_id == $this->getTargetOptionGroupId()) {
+      return parent::getReferenceCount($targetDao);
+    } else {
+      return NULL;
+    }
+  }
+
   public function getTargetOptionGroupId() {
     if ($this->targetOptionGroupId === NULL) {
       $this->targetOptionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $this->targetOptionGroupName, 'id', 'name');
index b5648293650743a6087ccccefd2e284c7fc44508..55ea4e5ed886e0cd1effe5c54c8aeb80a596c072 100644 (file)
@@ -69,6 +69,50 @@ class CRM_Core_DAOTest extends CiviUnitTestCase {
     $this->assertEquals($contact->id, $refDao->contact_id);
   }
 
+  function testGetReferenceCounts() {
+    $result = $this->callAPISuccess('Contact', 'create', array(
+      'first_name' => 'Testily',
+      'last_name' => 'McHaste',
+      'contact_type' => 'Individual',
+      'api.Email.replace' => array(
+        'values' => array(
+          array(
+            'email' => 'spam@dev.null',
+            'is_primary' => 0,
+            'location_type_id' => 1,
+          )
+        ),
+      ),
+      'api.Phone.replace' => array(
+        'values' => array(
+          array(
+            'phone' => '234-567-0001',
+            'is_primary' => 1,
+            'location_type_id' => 1,
+          ),
+          array(
+            'phone' => '234-567-0002',
+            'is_primary' => 0,
+            'location_type_id' => 1,
+          ),
+        ),
+      ),
+    ));
+
+    $dao = new CRM_Contact_BAO_Contact();
+    $dao->id = $result['id'];
+    $this->assertTrue((bool) $dao->find(TRUE));
+
+    $refCounts = $dao->getReferenceCounts();
+    $this->assertTrue(is_array($refCounts));
+    $refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
+    $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
+    $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
+    $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
+    $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
+    $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
+  }
+
   function composeQueryExamples() {
     $cases = array();
     // $cases[] = array('Input-SQL', 'Input-Params', 'Expected-SQL');