3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
13 * Class CRM_Contact_BAO_RelationshipCache.
15 class CRM_Contact_BAO_RelationshipCache
extends CRM_Contact_DAO_RelationshipCache
{
18 * The "mappings" array defines the values to put into `civicrm_relationship_cache`
19 * using data from `civicrm_relationship rel` and `civicrm_relationship_type reltype`.
22 * Array(string $intoColumn => string $selectValue)
24 private static $mappings = [
26 'relationship_id' => 'rel.id',
27 'relationship_type_id' => 'rel.relationship_type_id',
28 'orientation' => '"a_b"',
29 'near_contact_id' => 'rel.contact_id_a',
30 'near_relation' => 'reltype.name_a_b',
31 'far_contact_id' => 'rel.contact_id_b',
32 'far_relation' => 'reltype.name_b_a',
33 'start_date' => 'rel.start_date',
34 'end_date' => 'rel.end_date',
35 'is_active' => 'rel.is_active',
38 'relationship_id' => 'rel.id',
39 'relationship_type_id' => 'rel.relationship_type_id',
40 'orientation' => '"b_a"',
41 'near_contact_id' => 'rel.contact_id_b',
42 'near_relation' => 'reltype.name_b_a',
43 'far_contact_id' => 'rel.contact_id_a',
44 'far_relation' => 'reltype.name_a_b',
45 'start_date' => 'rel.start_date',
46 'end_date' => 'rel.end_date',
47 'is_active' => 'rel.is_active',
52 * A list of fields which uniquely identify a row.
56 private static $keyFields = ['relationship_id', 'orientation'];
59 * A list of of fields in `civicrm_relationship_type` which (if changed)
60 * will necessitate an update to the cache.
64 private static $relTypeWatchFields = ['name_a_b', 'name_b_a'];
67 * Add our list of triggers to the global list.
69 * @param \Civi\Core\Event\GenericHookEvent $e
70 * @see \CRM_Utils_Hook::triggerInfo
72 public static function onHookTriggerInfo($e) {
73 $relUpdates = self
::createInsertUpdateQueries();
74 foreach ($relUpdates as $relUpdate) {
76 * This trigger runs whenever a "civicrm_relationship" record is inserted or updated.
78 * Goal: Ensure that every relationship record has two corresponding entries in the
79 * cache, the forward relationship (A=>B) and reverse relationship (B=>A).
82 'table' => 'civicrm_relationship',
84 'event' => ['INSERT', 'UPDATE'],
85 'sql' => $relUpdate->copy()->where('rel.id = NEW.id')->toSQL() . ";\n",
90 * This trigger runs whenever a "civicrm_relationship_type" record is updated.
92 * Goal: Ensure that the denormalized fields ("name_b_a"/"name_a_b" <=> "relation") remain current.
94 'table' => 'civicrm_relationship_type',
96 'event' => ['UPDATE'],
97 'sql' => sprintf("\nIF (%s) THEN\n %s;\n END IF;\n",
100 implode(' OR ', array_map(function ($col) {
101 return "(OLD.$col != NEW.$col COLLATE utf8_bin)";
102 }, self
::$relTypeWatchFields)),
105 $relUpdate->copy()->where('rel.relationship_type_id = NEW.id')->toSQL()
110 // Note: We do not need a DELETE trigger to maintain `civicrm_relationship_cache` because it uses `<onDelete>CASCADE</onDelete>`.
112 $st = new \Civi\Core\SqlTrigger\
StaticTriggers($triggers);
113 $st->onTriggerInfo($e);
117 * Read all records from civicrm_relationship and populate the cache.
118 * Each ordinary relationship in `civicrm_relationship` becomes two
119 * distinct records in the cache (one for A=>B relations; and one for B=>A).
121 * This method is primarily written (a) for manual testing and (b) in case
122 * a broken DBMS, screwy import, buggy code, etc causes a corruption.
124 * NOTE: This is closely related to FiveTwentyNine::populateRelationshipCache(),
125 * except that the upgrader users pagination.
127 public static function rebuild() {
128 $relUpdates = self
::createInsertUpdateQueries();
130 CRM_Core_DAO
::executeQuery('TRUNCATE civicrm_relationship_cache');
131 foreach ($relUpdates as $relUpdate) {
132 $relUpdate->execute();
137 * Prepare a list of SQL queries that map data from civicrm_relationship
138 * to civicrm_relationship_cache.
140 * @return CRM_Utils_SQL_Select[]
141 * A list of SQL queries - one for each mapping.
143 public static function createInsertUpdateQueries() {
145 foreach (self
::$mappings as $name => $mapping) {
146 $queries[$name] = CRM_Utils_SQL_Select
::from('civicrm_relationship rel')
147 ->join('reltype', 'INNER JOIN civicrm_relationship_type reltype ON rel.relationship_type_id = reltype.id')
148 ->syncInto('civicrm_relationship_cache', self
::$keyFields, $mapping);