CRM-19130 - xml/templates/dao.tpl - Fire events for fields() and links()
authorTim Otten <totten@civicrm.org>
Fri, 29 Jul 2016 02:37:55 +0000 (19:37 -0700)
committerTim Otten <totten@civicrm.org>
Fri, 29 Jul 2016 02:42:05 +0000 (19:42 -0700)
CRM/Core/DAO/AllCoreTables.php
CRM/Utils/Hook.php
tests/phpunit/CRM/Core/DAO/AllCoreTablesTest.php
xml/templates/dao.tpl

index 21fc67e8470b0a6a5af488d9278d0c4712a61ed6..2fced2a763d293c401be265e3cf876250bd8063b 100644 (file)
@@ -44,6 +44,7 @@ class CRM_Core_DAO_AllCoreTables {
     if ($init && !$fresh) {
       return;
     }
+    Civi::$statics[__CLASS__] = array();
 
     $file = preg_replace('/\.php$/', '.data.php', __FILE__);
     $entityTypes = require $file;
@@ -53,8 +54,13 @@ class CRM_Core_DAO_AllCoreTables {
     self::$tables = array();
     self::$daoToClass = array();
     foreach ($entityTypes as $entityType) {
-      self::registerEntityType($entityType['name'], $entityType['class'],
-        $entityType['table']);
+      self::registerEntityType(
+        $entityType['name'],
+        $entityType['class'],
+        $entityType['table'],
+        isset($entityType['fields_callback']) ? $entityType['fields_callback'] : NULL,
+        isset($entityType['links_callback']) ? $entityType['links_callback'] : NULL
+      );
     }
 
     $init = TRUE;
@@ -63,13 +69,15 @@ class CRM_Core_DAO_AllCoreTables {
   /**
    * (Quasi-Private) Do not call externally (except for unit-testing)
    */
-  public static function registerEntityType($daoName, $className, $tableName) {
+  public static function registerEntityType($daoName, $className, $tableName, $fields_callback = NULL, $links_callback = NULL) {
     self::$daoToClass[$daoName] = $className;
     self::$tables[$tableName] = $className;
     self::$entityTypes[$className] = array(
       'name' => $daoName,
       'class' => $className,
       'table' => $tableName,
+      'fields_callback' => $fields_callback,
+      'links_callback' => $links_callback,
     );
   }
 
@@ -251,4 +259,23 @@ class CRM_Core_DAO_AllCoreTables {
     return Civi::$statics[__CLASS__][$cacheKey];
   }
 
+  /**
+   * (Quasi-Private) Do not call externally. For use by DAOs.
+   *
+   * Apply any third-party alterations to the `fields()`.
+   *
+   * @param string $className
+   * @param string $event
+   * @param mixed $values
+   */
+  public static function invoke($className, $event, &$values) {
+    self::init();
+    if (isset(self::$entityTypes[$className][$event])) {
+      foreach (self::$entityTypes[$className][$event] as $filter) {
+        $args = array($className, &$values);
+        \Civi\Core\Resolver::singleton()->call($filter, $args);
+      }
+    }
+  }
+
 }
index a60b911bcb16726e1d34739dbe6ef534f3909186..7bec5213c017cc44c5bad8fadb9f39931527d8be 100644 (file)
@@ -1740,6 +1740,8 @@ abstract class CRM_Utils_Hook {
    *   - name: string, a unique short name (e.g. "ReportInstance")
    *   - class: string, a PHP DAO class (e.g. "CRM_Report_DAO_Instance")
    *   - table: string, a SQL table name (e.g. "civicrm_report_instance")
+   *   - fields_callback: array, list of callables which manipulates field list
+   *   - links_callback: array, list of callables which manipulates fk list
    *
    * @return null
    *   The return value is ignored
index 132e10b1f6f3fe008b70c0eb3ea4114514acd26b..ab9819b37be17b82cbf9c1f5af6ac93b55c52c2b 100644 (file)
@@ -9,4 +9,43 @@ class CRM_Core_DAO_AllCoreTablesTest extends CiviUnitTestCase {
     $this->assertEquals('civicrm_email', CRM_Core_DAO_AllCoreTables::getTableForClass('CRM_Core_DAO_Email'));
     $this->assertEquals('civicrm_email', CRM_Core_DAO_AllCoreTables::getTableForClass('CRM_Core_BAO_Email'));
   }
+
+  /**
+   * Ensure that hook_civicrm_entityTypes runs and correctly handles the
+   * 'fields_callback' option.
+   */
+  public function testHook() {
+    // 1. First, check the baseline fields()...
+    $fields = CRM_Core_DAO_Email::fields();
+    $this->assertFalse(isset($fields['location_type_id']['foo']));
+
+    $exports = CRM_Core_DAO_Email::export();
+    $this->assertFalse(isset($exports['contact_id']));
+
+    // 2. Now, let's hook into it...
+    $this->hookClass->setHook('civicrm_entityTypes', array($this, '_hook_civicrm_entityTypes'));
+    unset(Civi::$statics['CRM_Core_DAO_Email']);
+    CRM_Core_DAO_AllCoreTables::init(1);
+
+    // 3. And see if the data has changed...
+    $fields = CRM_Core_DAO_Email::fields();
+    $this->assertEquals('bar', $fields['location_type_id']['foo']);
+
+    $exports = CRM_Core_DAO_Email::export();
+    $this->assertTrue(is_array($exports['contact_id']));
+  }
+
+  public function _hook_civicrm_entityTypes(&$entityTypes) {
+    $entityTypes['CRM_Core_DAO_Email']['fields_callback'][] = function ($class, &$fields) {
+      $fields['location_type_id']['foo'] = 'bar';
+      $fields['contact_id']['export'] = TRUE;
+    };
+  }
+
+  protected function tearDown() {
+    CRM_Utils_Hook::singleton()->reset();
+    CRM_Core_DAO_AllCoreTables::init(1);
+    parent::tearDown();
+  }
+
 }
index 3519b55ecdcf8d8f1fcc857e6c2a9e87f5f39318..fe5e9f87078549da07e86ea0738809746f31fc35 100644 (file)
@@ -46,20 +46,6 @@ class {$table.className} extends CRM_Core_DAO {ldelim}
       */
       static $_tableName = '{$table.name}';
 
-     /**
-      * static instance to hold the field values
-      *
-      * @var array
-      */
-      static $_fields = null;
-
-     /**
-      * static instance to hold the FK relationships
-      *
-      * @var string
-      */
-      static $_links = null;
-
       /**
        * static value to see if we should log any modifications to
        * this table in the civicrm_log table
@@ -99,17 +85,18 @@ class {$table.className} extends CRM_Core_DAO {ldelim}
      *   [CRM_Core_Reference_Interface]
      */
     static function getReferenceColumns() {ldelim}
-      if (!self::$_links) {ldelim}
-        self::$_links = static::createReferenceColumns(__CLASS__);
+      if (!isset(Civi::$statics[__CLASS__]['links'])) {ldelim}
+        Civi::$statics[__CLASS__]['links'] = static::createReferenceColumns(__CLASS__);
 {foreach from=$table.foreignKey item=foreign}
-        self::$_links[] = new CRM_Core_Reference_Basic(self::getTableName(), '{$foreign.name}', '{$foreign.table}', '{$foreign.key}');
+        Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName(), '{$foreign.name}', '{$foreign.table}', '{$foreign.key}');
 {/foreach}
 
 {foreach from=$table.dynamicForeignKey item=foreign}
-        self::$_links[] = new CRM_Core_Reference_Dynamic(self::getTableName(), '{$foreign.idColumn}', NULL, '{$foreign.key|default:'id'}', '{$foreign.typeColumn}');
+        Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Dynamic(self::getTableName(), '{$foreign.idColumn}', NULL, '{$foreign.key|default:'id'}', '{$foreign.typeColumn}');
 {/foreach}
+        CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', Civi::$statics[__CLASS__]['links']);
       {rdelim}
-      return self::$_links;
+      return Civi::$statics[__CLASS__]['links'];
     {rdelim}
 {/if} {* table.foreignKey *}
 
@@ -119,8 +106,8 @@ class {$table.className} extends CRM_Core_DAO {ldelim}
        * @return array
        */
       static function &fields( ) {ldelim}
-        if ( ! ( self::$_fields ) ) {ldelim}
-               self::$_fields = array (
+        if ( ! isset(Civi::$statics[__CLASS__]['fields']) ) {ldelim}
+          Civi::$statics[__CLASS__]['fields'] = array (
 {foreach from=$table.fields item=field}
 
 {if $field.uniqueName}
@@ -200,8 +187,9 @@ class {$table.className} extends CRM_Core_DAO {ldelim}
 {/if} {* field.pseudoconstant *}                                                                    ),
 {/foreach} {* table.fields *}
                                       );
+            CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
           {rdelim}
-          return self::$_fields;
+          return Civi::$statics[__CLASS__]['fields'];
       {rdelim}
 
       /**