Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.38% covered (warning)
63.38%
45 / 71
50.00% covered (danger)
50.00%
4 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
RelationshipHooks
63.38% covered (warning)
63.38%
45 / 71
50.00% covered (danger)
50.00%
4 / 8
95.16
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 relationshipInsert
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 relationshipUpdate
76.92% covered (warning)
76.92%
10 / 13
0.00% covered (danger)
0.00%
0 / 1
6.44
 relationshipDelete
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
4.02
 getRelationshipContacts
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 incrementForRelationship
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 decrementForRelationship
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 handleContactChanges
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
132
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\crm\Hook;
6
7use Drupal\Core\Hook\Attribute\Hook;
8use Drupal\crm\Entity\RelationshipInterface;
9use Drupal\crm\Service\RelationshipStatisticsInterface;
10
11/**
12 * Hooks relating to relationship entities.
13 */
14class RelationshipHooks {
15
16  /**
17   * Constructs a RelationshipHooks object.
18   *
19   * @param \Drupal\crm\Service\RelationshipStatisticsInterface $statisticsService
20   *   The relationship statistics service.
21   */
22  public function __construct(
23    protected RelationshipStatisticsInterface $statisticsService,
24  ) {}
25
26  /**
27   * Implements hook_ENTITY_TYPE_insert() for crm_relationship.
28   */
29  #[Hook('crm_relationship_insert')]
30  public function relationshipInsert(RelationshipInterface $relationship): void {
31    // Only update statistics for active relationships.
32    if (!$relationship->get('status')->value) {
33      return;
34    }
35
36    $contacts = $this->getRelationshipContacts($relationship);
37
38    if ($contacts['a']) {
39      $type_key = $this->statisticsService->getTypeKey($relationship, 'a');
40      $this->statisticsService->increment($contacts['a'], $type_key);
41    }
42
43    if ($contacts['b']) {
44      $type_key = $this->statisticsService->getTypeKey($relationship, 'b');
45      $this->statisticsService->increment($contacts['b'], $type_key);
46    }
47  }
48
49  /**
50   * Implements hook_ENTITY_TYPE_update() for crm_relationship.
51   */
52  #[Hook('crm_relationship_update')]
53  public function relationshipUpdate(RelationshipInterface $relationship): void {
54    $original = $relationship->original ?? NULL;
55
56    $current_status = (bool) $relationship->get('status')->value;
57    $original_status = $original ? (bool) $original->get('status')->value : FALSE;
58
59    $current_contacts = $this->getRelationshipContacts($relationship);
60    $original_contacts = $original ? $this->getRelationshipContacts($original) : ['a' => NULL, 'b' => NULL];
61
62    // Handle status changes.
63    if ($current_status !== $original_status) {
64      if ($current_status) {
65        // Relationship became active - increment.
66        $this->incrementForRelationship($relationship, $current_contacts);
67      }
68      else {
69        // Relationship became inactive - decrement.
70        $this->decrementForRelationship($relationship, $current_contacts);
71      }
72      return;
73    }
74
75    // If relationship is inactive, no statistics changes needed.
76    if (!$current_status) {
77      return;
78    }
79
80    // Handle contact reference changes.
81    $this->handleContactChanges($relationship, $original_contacts, $current_contacts);
82  }
83
84  /**
85   * Implements hook_ENTITY_TYPE_delete() for crm_relationship.
86   */
87  #[Hook('crm_relationship_delete')]
88  public function relationshipDelete(RelationshipInterface $relationship): void {
89    // Only update statistics for active relationships.
90    if (!$relationship->get('status')->value) {
91      return;
92    }
93
94    $contacts = $this->getRelationshipContacts($relationship);
95
96    if ($contacts['a']) {
97      $type_key = $this->statisticsService->getTypeKey($relationship, 'a');
98      $this->statisticsService->decrement($contacts['a'], $type_key);
99    }
100
101    if ($contacts['b']) {
102      $type_key = $this->statisticsService->getTypeKey($relationship, 'b');
103      $this->statisticsService->decrement($contacts['b'], $type_key);
104    }
105  }
106
107  /**
108   * Gets the contact entities from a relationship.
109   *
110   * @param \Drupal\crm\RelationshipInterface $relationship
111   *   The relationship entity.
112   *
113   * @return array
114   *   An array with 'a' and 'b' keys containing contact entities or NULL.
115   */
116  protected function getRelationshipContacts(RelationshipInterface $relationship): array {
117    $contacts_field = $relationship->get('contacts')->getValue();
118
119    $contact_a = NULL;
120    $contact_b = NULL;
121
122    if (!empty($contacts_field[0]['target_id'])) {
123      $contact_a = $relationship->get('contact_a')->entity;
124    }
125
126    if (!empty($contacts_field[1]['target_id'])) {
127      $contact_b = $relationship->get('contact_b')->entity;
128    }
129
130    return [
131      'a' => $contact_a,
132      'b' => $contact_b,
133    ];
134  }
135
136  /**
137   * Increments statistics for both contacts in a relationship.
138   *
139   * @param \Drupal\crm\RelationshipInterface $relationship
140   *   The relationship entity.
141   * @param array $contacts
142   *   The contacts array with 'a' and 'b' keys.
143   */
144  protected function incrementForRelationship(RelationshipInterface $relationship, array $contacts): void {
145    if ($contacts['a']) {
146      $type_key = $this->statisticsService->getTypeKey($relationship, 'a');
147      $this->statisticsService->increment($contacts['a'], $type_key);
148    }
149
150    if ($contacts['b']) {
151      $type_key = $this->statisticsService->getTypeKey($relationship, 'b');
152      $this->statisticsService->increment($contacts['b'], $type_key);
153    }
154  }
155
156  /**
157   * Decrements statistics for both contacts in a relationship.
158   *
159   * @param \Drupal\crm\RelationshipInterface $relationship
160   *   The relationship entity.
161   * @param array $contacts
162   *   The contacts array with 'a' and 'b' keys.
163   */
164  protected function decrementForRelationship(RelationshipInterface $relationship, array $contacts): void {
165    if ($contacts['a']) {
166      $type_key = $this->statisticsService->getTypeKey($relationship, 'a');
167      $this->statisticsService->decrement($contacts['a'], $type_key);
168    }
169
170    if ($contacts['b']) {
171      $type_key = $this->statisticsService->getTypeKey($relationship, 'b');
172      $this->statisticsService->decrement($contacts['b'], $type_key);
173    }
174  }
175
176  /**
177   * Handles contact reference changes.
178   *
179   * @param \Drupal\crm\RelationshipInterface $relationship
180   *   The relationship entity.
181   * @param array $original_contacts
182   *   The original contacts array.
183   * @param array $current_contacts
184   *   The current contacts array.
185   */
186  protected function handleContactChanges(RelationshipInterface $relationship, array $original_contacts, array $current_contacts): void {
187    // Check if contact A changed.
188    $original_a_id = $original_contacts['a'] ? $original_contacts['a']->id() : NULL;
189    $current_a_id = $current_contacts['a'] ? $current_contacts['a']->id() : NULL;
190
191    if ($original_a_id !== $current_a_id) {
192      $type_key = $this->statisticsService->getTypeKey($relationship, 'a');
193
194      // Decrement from old contact.
195      if ($original_contacts['a']) {
196        $this->statisticsService->decrement($original_contacts['a'], $type_key);
197      }
198
199      // Increment on new contact.
200      if ($current_contacts['a']) {
201        $this->statisticsService->increment($current_contacts['a'], $type_key);
202      }
203    }
204
205    // Check if contact B changed.
206    $original_b_id = $original_contacts['b'] ? $original_contacts['b']->id() : NULL;
207    $current_b_id = $current_contacts['b'] ? $current_contacts['b']->id() : NULL;
208
209    if ($original_b_id !== $current_b_id) {
210      $type_key = $this->statisticsService->getTypeKey($relationship, 'b');
211
212      // Decrement from old contact.
213      if ($original_contacts['b']) {
214        $this->statisticsService->decrement($original_contacts['b'], $type_key);
215      }
216
217      // Increment on new contact.
218      if ($current_contacts['b']) {
219        $this->statisticsService->increment($current_contacts['b'], $type_key);
220      }
221    }
222  }
223
224}