Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
60.22% covered (warning)
60.22%
56 / 93
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
UserHooks
60.22% covered (warning)
60.22%
56 / 93
66.67% covered (warning)
66.67%
4 / 6
45.19
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
 userInsert
88.24% covered (warning)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
4.03
 userContactFormatNameAlter
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
6
 userFormAlter
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
30
 userFormAlterSubmit
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 userDelete
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace Drupal\crm\Hook;
4
5use Drupal\Core\Config\ConfigFactoryInterface;
6use Drupal\Core\Entity\EntityTypeManagerInterface;
7use Drupal\Core\Hook\Attribute\Hook;
8use Drupal\Core\Session\AccountInterface;
9use Drupal\crm\Event\CrmUserContactEvent;
10use Drupal\user\UserDataInterface;
11use Drupal\user\UserInterface;
12use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
13use Drupal\Core\Session\AccountProxyInterface;
14use Drupal\Core\Form\FormStateInterface;
15use Drupal\Core\StringTranslation\StringTranslationTrait;
16use Drupal\name\NameFormatterInterface;
17
18/**
19 * Hooks relating to users.
20 */
21class UserHooks {
22  use StringTranslationTrait;
23
24  public function __construct(
25    protected ConfigFactoryInterface $configFactory,
26    protected EntityTypeManagerInterface $entityTypeManager,
27    protected EventDispatcherInterface $eventDispatcher,
28    protected UserDataInterface $userData,
29    protected AccountProxyInterface $currentUser,
30    protected NameFormatterInterface $nameFormatter,
31  ) {}
32
33  /**
34   * Implements hook_ENTITY_TYPE_insert().
35   */
36  #[Hook('user_insert')]
37  public function userInsert(UserInterface $user) {
38
39    $auto_create_crm_user_contact = $this->configFactory
40      ->get('crm.user_contact.settings')
41      ->get('auto_create_crm_user_contact');
42    if (!$auto_create_crm_user_contact) {
43      return;
44    }
45
46    $crm_user_contact = $this->entityTypeManager
47      ->getStorage('crm_user_contact')
48      ->create(['user' => $user->id()]);
49    $event = new CrmUserContactEvent($crm_user_contact);
50    $this->eventDispatcher->dispatch($event, CrmUserContactEvent::EVENT_NAME);
51    $crm_user_contact = $event->getCrmUserContact();
52    $contact = $crm_user_contact->getContact();
53
54    if ($contact == NULL) {
55      return NULL;
56    }
57    if ($contact->get('bundle')->target_id != 'person') {
58      return NULL;
59    }
60
61    $crm_user_contact->save();
62  }
63
64  /**
65   * Implements hook_user_format_name_alter().
66   */
67  #[Hook('user_format_name_alter')]
68  public function userContactFormatNameAlter(&$name, AccountInterface $account) {
69    $override = $this->configFactory->get('crm.user_contact.settings')->get('display_name');
70    if (!$override) {
71      return;
72    }
73    $crm_users_contact = $this->entityTypeManager
74      ->getStorage('crm_user_contact')
75      ->loadByProperties(['user' => $account->id()]);
76    if ($crm_users_contact == NULL) {
77      return;
78    }
79    /** @var \Drupal\crm\Entity\UserContact */
80    $crm_user_contact = reset($crm_users_contact);
81    $contact = $crm_user_contact->getContact();
82    $name = $contact->label();
83
84    $user_name_format = $this->userData->get('crm', $account->id(), 'name_format');
85    if (!$user_name_format) {
86      return;
87    }
88    if (!$account->hasPermission('crm user alter display name')) {
89      return;
90    }
91
92    $name_array = $contact->get('full_name')->getValue();
93    if (empty($name_array)) {
94      return;
95    }
96    $name_array = $name_array[0];
97    $name_array['preferred'] = $contact->get('preferred_name')->value;
98    $name_array['alternative'] = array_map(function ($alias) {
99      return $alias['value'];
100    }, $contact->get('aliases')->getValue());
101    $name_array['alternative'] = implode(', ', $name_array['alternative']);
102
103    $formatted_name = $this->nameFormatter->format($name_array, $user_name_format);
104
105    $name = html_entity_decode($formatted_name, ENT_QUOTES | ENT_HTML5, 'UTF-8');
106
107  }
108
109  /**
110   * Implements hook_form_FORM_ID_alter().
111   */
112  #[Hook('form_user_form_alter')]
113  public function userFormAlter(&$form, FormStateInterface $form_state) {
114    $user_contact_settings = $this->configFactory->get('crm.user_contact.settings');
115
116    if (!$user_contact_settings->get('display_name')) {
117      return;
118    }
119
120    $form_user = $form_state->getFormObject()->getEntity();
121
122    $user_contact = $this->entityTypeManager
123      ->getStorage('crm_user_contact')
124      ->loadByProperties(['user' => $form_user->id()]);
125    if ($user_contact == NULL) {
126      return;
127    }
128
129    $user_contact = reset($user_contact);
130
131    $same_user = $this->currentUser->id() == $form_user->id();
132    if (!$same_user) {
133      return;
134    }
135
136    if (!$this->currentUser->hasPermission('crm user alter display name')) {
137      return;
138    }
139
140    $format_options = $this->entityTypeManager->getStorage('name_format')->loadMultiple();
141    $format_options = array_map(function ($format) {
142      return $format->label();
143    }, $format_options);
144
145    $person_contact_type = $user_contact->getContact()->get('bundle')->entity;
146    $system_format = $person_contact_type->getThirdPartySetting('crm', 'name_format', 'default');
147    $format_options = ['_none' => $this->t('System (@system)', ['@system' => $system_format])] + $format_options;
148
149    $user_name_format = $this->userData->get('crm', $form_user->id(), 'name_format');
150
151    $form['crm'] = [
152      '#type' => 'details',
153      '#title' => $this->t('CRM'),
154      '#open' => TRUE,
155    ];
156
157    $form['crm']['name_format'] = [
158      '#type' => 'select',
159      '#title' => $this->t('Name Format'),
160      '#options' => $format_options,
161      '#default_value' => $user_name_format,
162    ];
163
164    $form['actions']['submit']['#submit'][] = [static::class, 'userFormAlterSubmit'];
165  }
166
167  /**
168   * Static submit handler for user form alter.
169   */
170  public static function userFormAlterSubmit(array &$form, FormStateInterface $form_state) {
171
172    $form_user = $form_state->getFormObject()->getEntity();
173    $user_name_format = $form_state->getValue('name_format');
174
175    /** @var \Drupal\user\UserDataInterface $user_data */
176    $user_data = \Drupal::service('user.data');
177
178    if ($user_name_format == '_none') {
179      $user_data->delete('crm', $form_user->id(), 'name_format');
180      return;
181    }
182    $user_data->set('crm', $form_user->id(), 'name_format', $user_name_format);
183  }
184
185  /**
186   * Implements hook_ENTITY_TYPE_delete().
187   */
188  #[Hook('user_delete')]
189  public function userDelete(UserInterface $user) {
190    $crm_users_contact = $this->entityTypeManager
191      ->getStorage('crm_user_contact')
192      ->loadByProperties(['user' => $user->id()]);
193    if ($crm_users_contact != NULL) {
194      $crm_user_contact = reset($crm_users_contact);
195      $crm_user_contact->delete();
196    }
197  }
198
199}