From 71e5aa5ca52fb158fb91e0636d11b79593ef0929 Mon Sep 17 00:00:00 2001 From: Adam Roses Wight Date: Wed, 24 Apr 2013 16:16:40 -0700 Subject: [PATCH] DAO function to list all foreign key references to a table This patch also begins to formally describe the entity_id/entity_table references, introducing a new first-class object CRM_Core_EntityReference. We still need some way to describe the restrictions on the possible values of entity_table for each DAO, so that findReferences() doesn't have to scan all tables using a generic pointer. Note that I've broken compatibility with PEAR links(), this would be easy to reimplement if we need, but it was not being unused in core. --- CRM/Core/DAO.php | 99 ++++++++++++------- CRM/Core/EntityReference.php | 49 +++++++++ CRM/Financial/BAO/FinancialType.php | 50 +++------- api/api.php | 6 -- tests/phpunit/CRM/Core/DAOTest.php | 71 +++++++++++++ xml/GenCode.php | 22 +++++ xml/schema/ACL/ACL.xml | 5 + xml/schema/ACL/EntityRole.xml | 5 + xml/schema/Activity/ActivityAssignment.xml | 14 +++ xml/schema/Batch/EntityBatch.xml | 5 + xml/schema/Campaign/CampaignGroup.xml | 6 ++ xml/schema/Case/CaseActivity.xml | 6 ++ xml/schema/Contribute/Premium.xml | 5 + xml/schema/Core/ActionLog.xml | 5 + xml/schema/Core/Discount.xml | 9 ++ xml/schema/Core/EntityFile.xml | 7 +- xml/schema/Core/EntityTag.xml | 7 +- xml/schema/Core/Log.xml | 5 + xml/schema/Core/Note.xml | 5 + xml/schema/Core/UFJoin.xml | 5 + .../Financial/EntityFinancialAccount.xml | 5 + xml/schema/Financial/EntityFinancialTrxn.xml | 5 + xml/schema/Financial/FinancialItem.xml | 5 + xml/schema/Friend/Friend.xml | 9 +- xml/schema/Mailing/Group.xml | 4 + xml/schema/PCP/PCPBlock.xml | 11 +++ xml/schema/Pledge/PledgeBlock.xml | 7 +- xml/schema/Price/LineItem.xml | 5 + xml/schema/Price/SetEntity.xml | 5 + xml/schema/Project/Project.xml | 5 + xml/schema/Project/Task.xml | 10 ++ xml/schema/Project/TaskStatus.xml | 10 ++ xml/templates/dao.tpl | 25 +++-- 33 files changed, 398 insertions(+), 94 deletions(-) create mode 100644 CRM/Core/EntityReference.php create mode 100644 tests/phpunit/CRM/Core/DAOTest.php diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 6ba9978780..36e550521e 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -190,20 +190,7 @@ class CRM_Core_DAO extends DB_DataObject { * @access protected */ function initialize() { - $links = $this->links(); - if (empty($links)) { - return; - } - $this->_connect(); - - if (!isset($GLOBALS['_DB_DATAOBJECT']['LINKS'][$this->_database])) { - $GLOBALS['_DB_DATAOBJECT']['LINKS'][$this->_database] = array(); - } - - if (!array_key_exists($this->__table, $GLOBALS['_DB_DATAOBJECT']['LINKS'][$this->_database])) { - $GLOBALS['_DB_DATAOBJECT']['LINKS'][$this->_database][$this->__table] = $links; - } } /** @@ -240,12 +227,13 @@ class CRM_Core_DAO extends DB_DataObject { /** * returns list of FK relationships * + * @static * @access public * - * @return array + * @return array of CRM_Core_EntityReference */ - function links() { - return NULL; + static function getReferenceColumns() { + return array(); } /** @@ -273,9 +261,6 @@ class CRM_Core_DAO extends DB_DataObject { } } - // set the links - $this->links(); - return $table; } @@ -1687,30 +1672,70 @@ SELECT contact_id } /** - * Check the tables sent in, to see if there are any tables where there is a value for - * a column + * Find all records which refer to this entity. + * + * @return array of objects referencing this + */ + function findReferences() { + $links = self::getReferencesToTable(static::getTableName()); + + $occurrences = array(); + foreach ($links as $refSpec) { + $refColumn = $refSpec->getReferenceKey(); + $targetColumn = $refSpec->getTargetKey(); + $params = array(1 => array($this->$targetColumn, 'String')); + $sql = <<getReferenceTable()} +WHERE {$refColumn} = %1 +EOS; + if ($refSpec->isGeneric()) { + $params[2] = array(static::getTableName(), 'String'); + $sql .= <<getTypeColumn()} = %2 +EOS; + } + $daoName = CRM_Core_AllCoreTables::getClassForTable($refSpec->getReferenceTable()); + $result = self::executeQuery($sql, $params, TRUE, $daoName); + while ($result->fetch()) { + $obj = new $daoName(); + $obj->id = $result->id; + $occurrences[] = $obj; + } + } + + return $occurrences; + } + + /** + * List all tables which have hard foreign keys to this table. * - * This is typically used when we want to delete a row, but want to avoid the FK errors - * that it might cause due to this being a required FK + * For now, this returns a description of every entity_id/entity_table + * reference. + * TODO: filter dynamic entity references on the $tableName, based on + * schema metadata in dynamicForeignKey which enumerates a restricted + * set of possible entity_table's. * - * @param array an array of values (tableName, columnName) - * @param array the parameter array with the value and type - * @param array (reference) the tables which had an entry for this value + * @param string $tableName table referred to * - * @return boolean true if no value exists in all the tables - * @static + * @return array structure of table and column, listing every table with a + * foreign key reference to $tableName, and the column where the key appears. */ - public static function doesValueExistInTable(&$tables, $params, &$errors) { - $errors = array(); - foreach ($tables as $table) { - $sql = "SELECT count(*) FROM {$table['table']} WHERE {$table['column']} = %1"; - $count = self::singleValueQuery($sql, $params); - if ($count > 0) { - $errors[$table['table']] = $count; + static function getReferencesToTable($tableName) { + $refsFound = array(); + foreach (CRM_Core_AllCoreTables::getClasses() as $daoClassName) { + $links = $daoClassName::getReferenceColumns(); + $daoTableName = $daoClassName::getTableName(); + + foreach ($links as $refSpec) { + if ($refSpec->getTargetTable() === $tableName + or $refSpec->isGeneric() + ) { + $refsFound[] = $refSpec; + } } } - - return (empty($errors)) ? FALSE : TRUE; + return $refsFound; } /** diff --git a/CRM/Core/EntityReference.php b/CRM/Core/EntityReference.php new file mode 100644 index 0000000000..3b5312833d --- /dev/null +++ b/CRM/Core/EntityReference.php @@ -0,0 +1,49 @@ +refTable = $refTable; + $this->refKey = $refKey; + $this->targetTable = $targetTable; + $this->targetKey = $targetKey; + $this->refTypeColumn = $refTypeColumn; + } + + function getReferenceTable() { + return $this->refTable; + } + + function getReferenceKey() { + return $this->refKey; + } + + function getTypeColumn() { + return $this->refTypeColumn; + } + + function getTargetTable() { + return $this->targetTable; + } + + function getTargetKey() { + return $this->targetKey; + } + + /** + * @return true if the reference can point to more than one type + */ + function isGeneric() { + return ($this->refTypeColumn !== NULL); + } +} diff --git a/CRM/Financial/BAO/FinancialType.php b/CRM/Financial/BAO/FinancialType.php index d2f6d36d22..5ac611d3d5 100644 --- a/CRM/Financial/BAO/FinancialType.php +++ b/CRM/Financial/BAO/FinancialType.php @@ -117,39 +117,19 @@ class CRM_Financial_BAO_FinancialType extends CRM_Financial_DAO_FinancialType { * @static */ static function del($financialTypeId) { - //checking if financial type is present - $check = false; - - // ensure that we have no objects that have an FK to this financial type id that cannot be null - $tables = - array( - array( - 'table' => 'civicrm_contribution', - 'column' => 'financial_type_id' - ), - array( - 'table' => 'civicrm_contribution_page', - 'column' => 'financial_type_id' - ), - array( - 'table' => 'civicrm_contribution_recur', - 'column' => 'financial_type_id' - ), - array( - 'table' => 'civicrm_membership_type', - 'column' => 'financial_type_id' - ), - array( - 'table' => 'civicrm_pledge', - 'column' => 'financial_type_id', - ), - ); - - $errors = array(); - $params = array( 1 => array($financialTypeId, 'Integer')); - if (CRM_Core_DAO::doesValueExistInTable( $tables, $params, $errors)) { - $message = ts('The following tables have an entry for this financial type') . ': '; - $message .= implode( ', ', array_keys($errors)); + $financialType = new CRM_Financial_DAO_FinancialType( ); + $financialType->id = $financialTypeId; + $financialType->find(true); + //TODO: if (!$financialType->find(true)) { + + // ensure that we have no objects that have an FK to this financial type id TODO: that cannot be null + $occurrences = $financialType->findReferences(); + if ($occurrences) { + $tables = array(); + foreach ($occurrences as $occurence) { + $tables[] = get_class($occurence); + } + $message = ts('The following tables have an entry for this financial type: %1', array( '%1' => implode(', ', $tables) )); $errors = array(); $errors['is_error'] = 1; @@ -158,14 +138,12 @@ class CRM_Financial_BAO_FinancialType extends CRM_Financial_DAO_FinancialType { } //delete from financial Type table - $financialType = new CRM_Financial_DAO_FinancialType( ); - $financialType->id = $financialTypeId; $financialType->delete(); $entityFinancialType = new CRM_Financial_DAO_EntityFinancialAccount( ); $entityFinancialType->entity_id = $financialTypeId; $entityFinancialType->entity_table = 'civicrm_financial_type'; - $entityFinancialType ->delete(); + $entityFinancialType->delete(); return FALSE; } diff --git a/api/api.php b/api/api.php index a494d28635..dd79c69f59 100644 --- a/api/api.php +++ b/api/api.php @@ -354,16 +354,10 @@ function civicrm_error($result) { } function _civicrm_api_get_camel_name($entity, $version = NULL) { - static $_map = NULL; - if (empty($version)) { $version = civicrm_get_api_version(); } - if (isset($_map[$version][strtolower($entity)])) { - return $_map[$version][strtolower($entity)]; - } - $fragments = explode('_', $entity); foreach ($fragments as & $fragment) { $fragment = ucfirst($fragment); diff --git a/tests/phpunit/CRM/Core/DAOTest.php b/tests/phpunit/CRM/Core/DAOTest.php new file mode 100644 index 0000000000..8bad54cf3c --- /dev/null +++ b/tests/phpunit/CRM/Core/DAOTest.php @@ -0,0 +1,71 @@ + 'DAO', + 'description' => 'Test core DAO functions', + 'group' => 'Core', + ); + } + + function testGetReferenceColumns() { + // choose CRM_Core_DAO_Email as an arbitrary example + $emailRefs = CRM_Core_DAO_Email::getReferenceColumns(); + $refsByTarget = array(); + foreach ($emailRefs as $refSpec) { + $refsByTarget[$refSpec->getTargetTable()] = $refSpec; + } + $this->assertTrue(array_key_exists('civicrm_contact', $refsByTarget)); + $contactRef = $refsByTarget['civicrm_contact']; + $this->assertEquals('contact_id', $contactRef->getReferenceKey()); + $this->assertEquals('id', $contactRef->getTargetKey()); + $this->assertEquals(FALSE, $contactRef->isGeneric()); + } + + function testGetReferencesToTable() { + $refs = CRM_Core_DAO::getReferencesToTable(CRM_Financial_DAO_FinancialType::getTableName()); + $refsBySource = array(); + foreach ($refs as $refSpec) { + $refsBySource[$refSpec->getReferenceTable()] = $refSpec; + } + $this->assertTrue(array_key_exists('civicrm_entity_financial_account', $refsBySource)); + $genericRef = $refsBySource['civicrm_entity_financial_account']; + $this->assertEquals('entity_id', $genericRef->getReferenceKey()); + $this->assertEquals('entity_table', $genericRef->getTypeColumn()); + $this->assertEquals('id', $genericRef->getTargetKey()); + $this->assertEquals(TRUE, $genericRef->isGeneric()); + } + + function testFindReferences() { + $params = array( + 'first_name' => 'Testy', + 'last_name' => 'McScallion', + 'contact_type' => 'Individual', + ); + + $contact = CRM_Contact_BAO_Contact::add($params); + $this->assertNotNull($contact->id); + + $params = array( + 'email' => 'spam@dev.null', + 'contact_id' => $contact->id, + 'is_primary' => 0, + 'location_type_id' => 1, + ); + + $email = CRM_Core_BAO_Email::add($params); + + $refs = $contact->findReferences(); + $refsByTable = array(); + foreach ($refs as $refObj) { + $refsByTable[$refObj->__table] = $refObj; + } + + $this->assertTrue(array_key_exists('civicrm_email', $refsByTable)); + $refDao = $refsByTable['civicrm_email']; + $refDao->find(TRUE); + $this->assertEquals($contact->id, $refDao->contact_id); + } +} diff --git a/xml/GenCode.php b/xml/GenCode.php index 70a2f4bbaf..d8ed559af6 100644 --- a/xml/GenCode.php +++ b/xml/GenCode.php @@ -585,6 +585,19 @@ Alternatively you can get a version of CiviCRM that matches your PHP version $table['foreignKey'] = &$foreign; } + if ($this->value('dynamicForeignKey', $tableXML)) { + $dynamicForeign = array(); + foreach ($tableXML->dynamicForeignKey as $foreignXML) { + if ($this->value('drop', $foreignXML, 0) > 0 and $this->value('drop', $foreignXML, 0) <= $this->buildVersion) { + continue; + } + if ($this->value('add', $foreignXML, 0) <= $this->buildVersion) { + $this->getDynamicForeignKey($foreignXML, $dynamicForeign, $name); + } + } + $table['dynamicForeignKey'] = $dynamicForeign; + } + $tables[$name] = &$table; return; } @@ -828,6 +841,15 @@ Alternatively you can get a version of CiviCRM that matches your PHP version $foreignKeys[$name] = &$foreignKey; } + function getDynamicForeignKey(&$foreignXML, &$dynamicForeignKeys) { + $foreignKey = array( + 'idColumn' => trim($foreignXML->idColumn), + 'typeColumn' => trim($foreignXML->typeColumn), + 'key' => trim($this->value('key', $foreignXML)), + ); + $dynamicForeignKeys[] = $foreignKey; + } + protected function value($key, &$object, $default = NULL) { if (isset($object->$key)) { return (string ) $object->$key; diff --git a/xml/schema/ACL/ACL.xml b/xml/schema/ACL/ACL.xml index a692e98811..9f43be1360 100644 --- a/xml/schema/ACL/ACL.xml +++ b/xml/schema/ACL/ACL.xml @@ -47,6 +47,11 @@ ID of the object possessing this ACL 1.6 + + entity_id + entity_table + 1.6 + operation enum diff --git a/xml/schema/ACL/EntityRole.xml b/xml/schema/ACL/EntityRole.xml index 87fb370aac..80eaf5f10b 100644 --- a/xml/schema/ACL/EntityRole.xml +++ b/xml/schema/ACL/EntityRole.xml @@ -39,6 +39,11 @@ ID of the group/contact object being joined 1.6 + + entity_id + entity_table + 1.6 + is_active boolean diff --git a/xml/schema/Activity/ActivityAssignment.xml b/xml/schema/Activity/ActivityAssignment.xml index b5daaa1859..a60ddab71e 100644 --- a/xml/schema/Activity/ActivityAssignment.xml +++ b/xml/schema/Activity/ActivityAssignment.xml @@ -38,6 +38,13 @@ 2.0 + + activity_entity_id + activity_entity_table + 1.8 + 2.0 + + target_entity_table varchar @@ -57,6 +64,13 @@ 2.0 + + target_entity_id + target_entity_table + 1.8 + 2.0 + + activity_id int unsigned diff --git a/xml/schema/Batch/EntityBatch.xml b/xml/schema/Batch/EntityBatch.xml index 4131a28b51..1ab00dd36e 100644 --- a/xml/schema/Batch/EntityBatch.xml +++ b/xml/schema/Batch/EntityBatch.xml @@ -30,6 +30,11 @@ FK to entity table specified in entity_table column. 3.3 + + entity_id + entity_table + 3.3 + index_entity entity_table diff --git a/xml/schema/Campaign/CampaignGroup.xml b/xml/schema/Campaign/CampaignGroup.xml index 059adbfd8a..04de043b7b 100644 --- a/xml/schema/Campaign/CampaignGroup.xml +++ b/xml/schema/Campaign/CampaignGroup.xml @@ -57,4 +57,10 @@ Entity id of referenced table. 3.3 + + + entity_id + entity_table + 3.3 + diff --git a/xml/schema/Case/CaseActivity.xml b/xml/schema/Case/CaseActivity.xml index 68e96231a3..562fa5f2d0 100644 --- a/xml/schema/Case/CaseActivity.xml +++ b/xml/schema/Case/CaseActivity.xml @@ -72,5 +72,11 @@ 2.0 + + activity_entity_id + activity_entity_table + 1.8 + 2.0 + diff --git a/xml/schema/Contribute/Premium.xml b/xml/schema/Contribute/Premium.xml index d6a1eb3efb..0d7e215514 100644 --- a/xml/schema/Contribute/Premium.xml +++ b/xml/schema/Contribute/Premium.xml @@ -31,6 +31,11 @@ true 1.4 + + entity_id + entity_table + 1.4 + premiums_active boolean diff --git a/xml/schema/Core/ActionLog.xml b/xml/schema/Core/ActionLog.xml index b890ac6250..09f05039b2 100644 --- a/xml/schema/Core/ActionLog.xml +++ b/xml/schema/Core/ActionLog.xml @@ -43,6 +43,11 @@ name of the entity table for the above id, e.g. civicrm_activity, civicrm_participant 3.4 + + entity_id + entity_table + 3.4 + action_schedule_id int unsigned diff --git a/xml/schema/Core/Discount.xml b/xml/schema/Core/Discount.xml index e1a4885af4..7596da2185 100644 --- a/xml/schema/Core/Discount.xml +++ b/xml/schema/Core/Discount.xml @@ -31,6 +31,11 @@ FK to entity table specified in entity_table column. 2.1 + + entity_id + entity_table + 2.1 + index_entity entity_table @@ -73,6 +78,10 @@ 4.3 CASCADE + + entity_id + entity_table + index_entity_option_id entity_table diff --git a/xml/schema/Core/EntityFile.xml b/xml/schema/Core/EntityFile.xml index fdfb1ce3af..bfd8260601 100644 --- a/xml/schema/Core/EntityFile.xml +++ b/xml/schema/Core/EntityFile.xml @@ -29,8 +29,13 @@ int unsigned true FK to entity table specified in entity_table column. - 1.5 + 1.5 + + entity_id + entity_table + 1.5 + index_entity entity_table diff --git a/xml/schema/Core/EntityTag.xml b/xml/schema/Core/EntityTag.xml index 495795ad9b..6875b2136e 100644 --- a/xml/schema/Core/EntityTag.xml +++ b/xml/schema/Core/EntityTag.xml @@ -48,8 +48,13 @@ Entity ID true FK to entity table specified in entity_table column. - 3.2 + 3.2 + + entity_id + entity_table + 3.2 + index_entity entity_table diff --git a/xml/schema/Core/Log.xml b/xml/schema/Core/Log.xml index fc3c6d93ef..fccbe8ac37 100644 --- a/xml/schema/Core/Log.xml +++ b/xml/schema/Core/Log.xml @@ -32,6 +32,11 @@ Foreign key to the referenced item. 1.5 + + entity_id + entity_table + 1.5 + index_entity 1.5 diff --git a/xml/schema/Core/Note.xml b/xml/schema/Core/Note.xml index 361fc1f558..9934fb4d05 100644 --- a/xml/schema/Core/Note.xml +++ b/xml/schema/Core/Note.xml @@ -33,6 +33,11 @@ Foreign key to the referenced item. 1.1 + + entity_id + entity_table + 1.1 + index_entity entity_table diff --git a/xml/schema/Core/UFJoin.xml b/xml/schema/Core/UFJoin.xml index 6ed456b82d..64c539329f 100644 --- a/xml/schema/Core/UFJoin.xml +++ b/xml/schema/Core/UFJoin.xml @@ -46,6 +46,11 @@ Foreign key to the referenced item. 1.3 + + entity_id + entity_table + 1.3 + index_entity 1.3 diff --git a/xml/schema/Financial/EntityFinancialAccount.xml b/xml/schema/Financial/EntityFinancialAccount.xml index 388521e7c9..edd95ff798 100755 --- a/xml/schema/Financial/EntityFinancialAccount.xml +++ b/xml/schema/Financial/EntityFinancialAccount.xml @@ -34,6 +34,11 @@ 4.3 Links to an id in the entity_table, such as vid in civicrm_financial_type + + entity_id + entity_table + 4.3 + account_relationship int unsigned diff --git a/xml/schema/Financial/EntityFinancialTrxn.xml b/xml/schema/Financial/EntityFinancialTrxn.xml index 4df5272415..26935a5b8f 100755 --- a/xml/schema/Financial/EntityFinancialTrxn.xml +++ b/xml/schema/Financial/EntityFinancialTrxn.xml @@ -31,6 +31,11 @@ true 3.2 + + entity_id + entity_table + 3.2 + financial_trxn_id int unsigned diff --git a/xml/schema/Financial/FinancialItem.xml b/xml/schema/Financial/FinancialItem.xml index 390fbc31aa..540387acc7 100644 --- a/xml/schema/Financial/FinancialItem.xml +++ b/xml/schema/Financial/FinancialItem.xml @@ -107,6 +107,11 @@ The specific source item that is responsible for the creation of this financial_item 4.3 + + entity_id + entity_table + 4.3 + UI_id id diff --git a/xml/schema/Friend/Friend.xml b/xml/schema/Friend/Friend.xml index 7930e5433c..f79a5fc6a2 100644 --- a/xml/schema/Friend/Friend.xml +++ b/xml/schema/Friend/Friend.xml @@ -30,8 +30,13 @@ true Foreign key to the referenced item. 2.0 - - + + + entity_id + entity_table + 2.0 + + title varchar 255 diff --git a/xml/schema/Mailing/Group.xml b/xml/schema/Mailing/Group.xml index 706012aa41..dafff0f9fd 100644 --- a/xml/schema/Mailing/Group.xml +++ b/xml/schema/Mailing/Group.xml @@ -46,6 +46,10 @@ true Foreign key to the referenced item. + + entity_id + entity_table + search_id int diff --git a/xml/schema/PCP/PCPBlock.xml b/xml/schema/PCP/PCPBlock.xml index 64dd578d3f..fbd6c504ee 100644 --- a/xml/schema/PCP/PCPBlock.xml +++ b/xml/schema/PCP/PCPBlock.xml @@ -31,6 +31,11 @@ FK to civicrm_contribution_page.id OR civicrm_event.id 2.2 + + entity_id + entity_table + 2.2 + entity_id civicrm_contribution_page
@@ -54,6 +59,12 @@ The entity that this pcp targets 4.1 + + target_entity_id + + target_entity_type + 4.1 + supporter_profile_id int unsigned diff --git a/xml/schema/Pledge/PledgeBlock.xml b/xml/schema/Pledge/PledgeBlock.xml index f3367ddc02..a5e1cf936f 100644 --- a/xml/schema/Pledge/PledgeBlock.xml +++ b/xml/schema/Pledge/PledgeBlock.xml @@ -30,8 +30,13 @@ int unsigned true FK to entity table specified in entity_table column. - 2.1 + 2.1 + + entity_id + entity_table + 2.1 + index_entity entity_table diff --git a/xml/schema/Price/LineItem.xml b/xml/schema/Price/LineItem.xml index a0c9115734..f37afc5246 100644 --- a/xml/schema/Price/LineItem.xml +++ b/xml/schema/Price/LineItem.xml @@ -32,6 +32,11 @@ entry in table 1.7 + + entity_id + entity_table + 1.7 + price_field_id int unsigned diff --git a/xml/schema/Price/SetEntity.xml b/xml/schema/Price/SetEntity.xml index af7c39870e..c16bb088b0 100644 --- a/xml/schema/Price/SetEntity.xml +++ b/xml/schema/Price/SetEntity.xml @@ -32,6 +32,11 @@ Item in table 1.8 + + entity_id + entity_table + 1.8 + price_set_id int unsigned diff --git a/xml/schema/Project/Project.xml b/xml/schema/Project/Project.xml index 44e3af90c2..3868915b90 100644 --- a/xml/schema/Project/Project.xml +++ b/xml/schema/Project/Project.xml @@ -59,6 +59,11 @@ Foreign key to project owner (contact, group, etc.). 1.5 + + owner_entity_id + owner_entity_table + 1.5 + start_date Start Date diff --git a/xml/schema/Project/Task.xml b/xml/schema/Project/Task.xml index 21e8934023..0782768664 100644 --- a/xml/schema/Project/Task.xml +++ b/xml/schema/Project/Task.xml @@ -57,6 +57,11 @@ Foreign key to Task owner (contact, group, etc.). 1.5 + + owner_entity_id + owner_entity_table + 1.5 + parent_entity_table varchar @@ -71,6 +76,11 @@ Optional foreign key to Task Parent (project, another task, etc.). 1.5 + + parent_entity_id + parent_entity_table + 1.5 + due_date Due Date diff --git a/xml/schema/Project/TaskStatus.xml b/xml/schema/Project/TaskStatus.xml index 1995ef1093..846997f499 100644 --- a/xml/schema/Project/TaskStatus.xml +++ b/xml/schema/Project/TaskStatus.xml @@ -47,6 +47,11 @@ Foreign key to responsible entity (contact, group, etc.). 1.5 + + responsible_entity_id + responsible_entity_table + 1.5 + target_entity_table varchar @@ -63,6 +68,11 @@ Foreign key to target entity (contact, group, etc.). 1.5 + + target_entity_id + target_entity_table + 1.5 + status_detail Status Details diff --git a/xml/templates/dao.tpl b/xml/templates/dao.tpl index e6ec545d8d..7f55dcf386 100644 --- a/xml/templates/dao.tpl +++ b/xml/templates/dao.tpl @@ -122,22 +122,27 @@ class {$table.className} extends CRM_Core_DAO {ldelim} parent::__construct( ); {rdelim} -{if $table.foreignKey} +{if $table.foreignKey || $table.dynamicForeignKey} /** - * return foreign links + * return foreign keys and entity references * + * @static * @access public - * @return array + * @return array of CRM_Core_EntityReference */ - function links( ) {ldelim} - if ( ! ( self::$_links ) ) {ldelim} - self::$_links = array( + static function getReferenceColumns() {ldelim} + if (!self::$_links) {ldelim} + self::$_links = array( {foreach from=$table.foreignKey item=foreign} - '{$foreign.name}' => '{$foreign.table}:{$foreign.key}', + new CRM_Core_EntityReference(self::getTableName(), '{$foreign.name}', '{$foreign.table}', '{$foreign.key}'), {/foreach} - ); - {rdelim} - return self::$_links; + +{foreach from=$table.dynamicForeignKey item=foreign} + new CRM_Core_EntityReference(self::getTableName(), '{$foreign.idColumn}', NULL, '{$foreign.key|default:'id'}', '{$foreign.typeColumn}'), +{/foreach} + ); + {rdelim} + return self::$_links; {rdelim} {/if} {* table.foreignKey *} -- 2.25.1