From: Aidan Saunders Date: Tue, 4 Apr 2017 22:56:29 +0000 (+1200) Subject: CRM-20312 Add indices to DAO classes X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=6b86d84f35a46b20e8414811f546edb38f3985e2;p=civicrm-core.git CRM-20312 Add indices to DAO classes --- diff --git a/CRM/Core/BAO/SchemaHandler.php b/CRM/Core/BAO/SchemaHandler.php index 9886c4378d..83c34d5852 100644 --- a/CRM/Core/BAO/SchemaHandler.php +++ b/CRM/Core/BAO/SchemaHandler.php @@ -644,4 +644,18 @@ MODIFY {$columnName} varchar( $length ) return FALSE; } + /** + * Add index signature hash to DAO file calculation. + * + * @param string $table table name + * @param array $indices index array spec + */ + public static function addIndexSignature($table, &$indices) { + foreach ($indices as $indexName => $index) { + $indices[$indexName]['sig'] = $table . "::" . + (array_key_exists('unique', $index) ? $index['unique'] : 0) . "::" . + implode("::", $index['field']); + } + } + } diff --git a/CRM/Core/CodeGen/DAO.php b/CRM/Core/CodeGen/DAO.php index 83c2c449d7..f0c6eec087 100644 --- a/CRM/Core/CodeGen/DAO.php +++ b/CRM/Core/CodeGen/DAO.php @@ -62,6 +62,12 @@ class CRM_Core_CodeGen_DAO extends CRM_Core_CodeGen_BaseTask { $template = new CRM_Core_CodeGen_Util_Template('php'); $template->assign('table', $this->tables[$this->name]); + if (empty($this->tables[$this->name]['index'])) { + $template->assign('indicesPhp', var_export(array(), 1)); + } + else { + $template->assign('indicesPhp', var_export($this->tables[$this->name]['index'], 1)); + } $template->assign('genCodeChecksum', $this->getTableChecksum()); $template->run('dao.tpl', $this->getAbsFileName()); } @@ -75,6 +81,12 @@ class CRM_Core_CodeGen_DAO extends CRM_Core_CodeGen_BaseTask { if (!$this->raw) { $template = new CRM_Core_CodeGen_Util_Template('php'); $template->assign('table', $this->tables[$this->name]); + if (empty($this->tables[$this->name]['index'])) { + $template->assign('indicesPhp', var_export(array(), 1)); + } + else { + $template->assign('indicesPhp', var_export($this->tables[$this->name]['index'], 1)); + } $template->assign('genCodeChecksum', 'NEW'); $this->raw = $template->fetch('dao.tpl'); } diff --git a/CRM/Core/CodeGen/Specification.php b/CRM/Core/CodeGen/Specification.php index 34d43015f0..7184d738d2 100644 --- a/CRM/Core/CodeGen/Specification.php +++ b/CRM/Core/CodeGen/Specification.php @@ -242,6 +242,7 @@ class CRM_Core_CodeGen_Specification { $this->getIndex($indexXML, $fields, $index); } + CRM_Core_BAO_SchemaHandler::addIndexSignature($name, $index); $table['index'] = &$index; } diff --git a/CRM/Core/DAO/AllCoreTables.php b/CRM/Core/DAO/AllCoreTables.php index 31987ffa43..f70d2a5bed 100644 --- a/CRM/Core/DAO/AllCoreTables.php +++ b/CRM/Core/DAO/AllCoreTables.php @@ -108,6 +108,70 @@ class CRM_Core_DAO_AllCoreTables { return self::$tables; } + /** + * @return array + * List of indices. + */ + public static function indices($localize = TRUE) { + $indices = array(); + self::init(); + foreach (self::$daoToClass as $class) { + if (is_callable(array($class, 'indices'))) { + $indices[$class::getTableName()] = $class::indices($localize); + } + } + return $indices; + } + + /** + * Modify indices to account for localization options. + * + * @param CRM_Core_DAO $class DAO class + * @param array $originalIndices index definitions before localization + * + * @return array + * index definitions after localization + */ + public static function multilingualize($class, $originalIndices) { + $domain = new CRM_Core_DAO_Domain(); + $domain->find(TRUE); + $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales); + if (CRM_Utils_System::isNull($locales)) { + return $originalIndices; + } + $classFields = $class::fields(); + + $finalIndices = array(); + foreach ($originalIndices as $index) { + if ($index['localizable']) { + foreach ($locales as $locale) { + $localIndex = $index; + $localIndex['name'] .= "_" . $locale; + $fields = array(); + foreach ($localIndex['field'] as $field) { + $baseField = explode('(', $field); + if ($classFields[$baseField[0]]['localizable']) { + // field name may have eg (3) at end for prefix length + // last_name => last_name_fr_FR + // last_name(3) => last_name_fr_FR(3) + $fields[] = preg_replace('/^([^(]+)(\(\d+\)|)$/', '${1}_' . $locale . '${2}', $field); + } + else { + $fields[] = $field; + } + } + $localIndex['field'] = $fields; + $finalIndices[$localIndex['name']] = $localIndex; + } + } + else { + $finalIndices[$index['name']] = $index; + } + } + CRM_Core_BAO_SchemaHandler::addIndexSignature(self::getTableForClass($class), $finalIndices); + return $finalIndices; + } + /** * @return array * Mapping from brief-names to class-names. diff --git a/tests/phpunit/CRM/Core/DAO/AllCoreTablesTest.php b/tests/phpunit/CRM/Core/DAO/AllCoreTablesTest.php index e93c8b1d79..7503e5a106 100644 --- a/tests/phpunit/CRM/Core/DAO/AllCoreTablesTest.php +++ b/tests/phpunit/CRM/Core/DAO/AllCoreTablesTest.php @@ -53,4 +53,155 @@ class CRM_Core_DAO_AllCoreTablesTest extends CiviUnitTestCase { parent::tearDown(); } + /** + * Test CRM_Core_DAO_AllCoreTables::indices() function. + * + * Ensure indices are listed correctly with and without localization + */ + public function testIndices() { + // civicrm_group UI_title is localizable + // Check indices without localization + $indices = CRM_Core_DAO_AllCoreTables::indices(FALSE); + $this->assertEquals($indices['civicrm_group']['UI_title']['name'], 'UI_title'); + $this->assertEquals($indices['civicrm_group']['UI_title']['sig'], 'civicrm_group::1::title'); + + // Not sure how we should be setting the locales, but this works for testing purposes + $domain = new CRM_Core_DAO_Domain(); + $domain->find(TRUE); + $domain->locales = implode(CRM_Core_DAO::VALUE_SEPARATOR, array('en_UK', 'fr_FR')); + $domain->save(); + + // Check indices with localization + $indices = CRM_Core_DAO_AllCoreTables::indices(TRUE); + $this->assertEquals($indices['civicrm_group']['UI_title_en_UK']['name'], 'UI_title_en_UK'); + $this->assertEquals($indices['civicrm_group']['UI_title_en_UK']['sig'], 'civicrm_group::1::title_en_UK'); + + $this->assertEquals($indices['civicrm_group']['UI_title_fr_FR']['name'], 'UI_title_fr_FR'); + $this->assertEquals($indices['civicrm_group']['UI_title_fr_FR']['sig'], 'civicrm_group::1::title_fr_FR'); + } + + /** + * Check CRM_Core_DAO_AllCoreTables::multilingualize() + */ + public function testMultilingualize() { + // in civicrm_group, title is localizable, name is not + $originalIndices = array( + 'test_index1' => array( + 'name' => 'test_index1', + 'field' => array( + 'name', + ), + 'localizable' => 0, + ), + 'test_index2' => array( + 'name' => 'test_index2', + 'field' => array( + 'title', + ), + 'localizable' => 1, + ), + 'test_index3' => array( + 'name' => 'test_index3', + 'field' => array( + 'name(3)', + ), + 'localizable' => 0, + ), + 'test_index4' => array( + 'name' => 'test_index4', + 'field' => array( + 'title(4)', + ), + 'localizable' => 1, + ), + 'test_index5' => array( + 'name' => 'test_index5', + 'field' => array( + 'title(4)', + 'name(3)', + ), + 'localizable' => 1, + ), + ); + + $expectedIndices = array( + 'test_index1' => array( + 'name' => 'test_index1', + 'field' => array( + 'name', + ), + 'localizable' => 0, + 'sig' => 'civicrm_group::0::name', + ), + 'test_index2_en_UK' => array( + 'name' => 'test_index2_en_UK', + 'field' => array( + 'title_en_UK', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_en_UK', + ), + 'test_index2_fr_FR' => array( + 'name' => 'test_index2_fr_FR', + 'field' => array( + 'title_fr_FR', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_fr_FR', + ), + 'test_index3' => array( + 'name' => 'test_index3', + 'field' => array( + 'name(3)', + ), + 'localizable' => 0, + 'sig' => 'civicrm_group::0::name(3)', + ), + 'test_index4_en_UK' => array( + 'name' => 'test_index4_en_UK', + 'field' => array( + 'title_en_UK(4)', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_en_UK(4)', + ), + 'test_index4_fr_FR' => array( + 'name' => 'test_index4_fr_FR', + 'field' => array( + 'title_fr_FR(4)', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_fr_FR(4)', + ), + 'test_index5_en_UK' => array( + 'name' => 'test_index5_en_UK', + 'field' => array( + 'title_en_UK(4)', + 'name(3)', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_en_UK(4)::name(3)', + ), + 'test_index5_fr_FR' => array( + 'name' => 'test_index5_fr_FR', + 'field' => array( + 'title_fr_FR(4)', + 'name(3)', + ), + 'localizable' => 1, + 'sig' => 'civicrm_group::0::title_fr_FR(4)::name(3)', + ), + ); + + // Not sure how we should be setting the locales, but this works for testing purposes + $domain = new CRM_Core_DAO_Domain(); + $domain->find(TRUE); + $domain->locales = implode(CRM_Core_DAO::VALUE_SEPARATOR, array('en_UK', 'fr_FR')); + $domain->save(); + + // needs a real DAO so use Group + $newIndices = CRM_Core_DAO_AllCoreTables::multilingualize('CRM_Contact_DAO_Group', $originalIndices); + $this->assertEquals($newIndices, $expectedIndices); + } + } diff --git a/xml/templates/dao.tpl b/xml/templates/dao.tpl index 22720d039a..4ba882ad1e 100644 --- a/xml/templates/dao.tpl +++ b/xml/templates/dao.tpl @@ -263,6 +263,11 @@ class {$table.className} extends CRM_Core_DAO {ldelim} return $r; {rdelim} + /** + * Returns the list of indices + */ + public static function indices($localize = TRUE) {ldelim} + $indices = {$indicesPhp}; + return ($localize && !empty($indices)) ? CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices; + {rdelim} {rdelim} - -