Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
207 / 207
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Contact
100.00% covered (success)
100.00%
207 / 207
100.00% covered (success)
100.00%
3 / 3
11
100.00% covered (success)
100.00%
1 / 1
 preSave
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 postSave
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 baseFieldDefinitions
100.00% covered (success)
100.00%
182 / 182
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\crm\Entity;
6
7use Drupal\Core\Entity\Attribute\ContentEntityType;
8use Drupal\Core\Entity\EntityChangedTrait;
9use Drupal\Core\Entity\EntityPublishedTrait;
10use Drupal\Core\Entity\EntityStorageInterface;
11use Drupal\Core\Entity\EntityTypeInterface;
12use Drupal\Core\Entity\RevisionableContentEntityBase;
13use Drupal\Core\Entity\RevisionLogEntityTrait;
14use Drupal\Core\Entity\Routing\AdminHtmlRouteProvider;
15use Drupal\Core\Field\BaseFieldDefinition;
16use Drupal\Core\StringTranslation\TranslatableMarkup;
17use Drupal\crm\ContactAccessControlHandler;
18use Drupal\crm\ContactListBuilder;
19use Drupal\crm\CrmContactInterface;
20use Drupal\crm\Form\ContactForm;
21use Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormComplex;
22use Drupal\views\EntityViewsData;
23use Drupal\Core\Entity\ContentEntityDeleteForm;
24use Drupal\crm\Field\AgeFieldItemList;
25
26/**
27 * CRM contact.
28 *
29 * A contact can be a person, an organization, a household, etc.
30 */
31#[ContentEntityType(
32  id: 'crm_contact',
33  label: new TranslatableMarkup('CRM Contact'),
34  label_collection: new TranslatableMarkup('CRM Contacts'),
35  label_singular: new TranslatableMarkup('crm contact'),
36  label_plural: new TranslatableMarkup('crm contacts'),
37  label_count: [
38    'singular' => '@count crm contact',
39    'plural' => '@count crm contacts',
40  ],
41  bundle_label: new TranslatableMarkup('Contact type'),
42  handlers: [
43    'list_builder' => ContactListBuilder::class,
44    'views_data' => EntityViewsData::class,
45    'access' => ContactAccessControlHandler::class,
46    'form' => [
47      'default' => ContactForm::class,
48      'delete' => ContentEntityDeleteForm::class,
49    ],
50    'route_provider' => [
51      'html' => AdminHtmlRouteProvider::class,
52    ],
53  ],
54  base_table: 'crm_contact',
55  revision_table: 'crm_contact_revision',
56  show_revision_ui: TRUE,
57  bundle_entity_type: 'crm_contact_type',
58  field_ui_base_route: 'entity.crm_contact_type.edit_form',
59  translatable: FALSE,
60  admin_permission: 'administer crm',
61  entity_keys: [
62    'id' => 'id',
63    'revision' => 'revision_id',
64    'bundle' => 'bundle',
65    'label' => 'name',
66    'uuid' => 'uuid',
67    'status' => 'status',
68    'published' => 'status',
69  ],
70  revision_metadata_keys: [
71    'revision_user' => 'revision_uid',
72    'revision_created' => 'revision_timestamp',
73    'revision_log_message' => 'revision_log',
74  ],
75  links: [
76    'add-page' => '/crm/contact/add',
77    'add-form' => '/crm/contact/add/{crm_contact_type}',
78    'canonical' => '/crm/contact/{crm_contact}',
79    'edit-form' => '/crm/contact/{crm_contact}/edit',
80    'delete-form' => '/crm/contact/{crm_contact}/delete',
81    'collection' => '/admin/content/crm/contact',
82  ],
83)]
84class Contact extends RevisionableContentEntityBase implements CrmContactInterface {
85  use EntityChangedTrait;
86  use EntityPublishedTrait;
87  use RevisionLogEntityTrait;
88
89  /**
90   * {@inheritdoc}
91   */
92  public function preSave(EntityStorageInterface $storage) {
93    parent::preSave($storage);
94    $this->setNewRevision();
95
96    // If type is person, set the label field to the name field.
97    if ($this->bundle() == 'person' && $this->hasField('full_name')) {
98      $name_array = $this->get('full_name')->getValue();
99      if (empty($name_array)) {
100        return;
101      }
102      $name_array = $name_array[0];
103      $name_array['preferred'] = $this->get('preferred_name')->value;
104      $name_array['alternative'] = array_map(function ($alias) {
105        return $alias['value'];
106      }, $this->get('aliases')->getValue());
107      $name_array['alternative'] = implode(', ', $name_array['alternative']);
108      $name_format = $this->bundle->entity->getThirdPartySetting('crm', 'name_format') ?? 'default';
109
110      $name_formatter = \Drupal::service('name.formatter');
111      $formatted_name = $name_formatter->format($name_array, $name_format);
112
113      $formatted_name = html_entity_decode($formatted_name, ENT_QUOTES | ENT_HTML5, 'UTF-8');
114      $this->set('name', $formatted_name);
115
116    }
117
118  }
119
120  /**
121   * {@inheritdoc}
122   */
123  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
124    parent::postSave($storage, $update);
125
126    $detail_fields = ['emails', 'telephones', 'addresses'];
127    foreach ($detail_fields as $detail_field) {
128      if (!$this->hasField($detail_field)) {
129        continue;
130      }
131      foreach ($this->get($detail_field) as $item) {
132        $detail = $item->entity;
133        if ($detail && $detail->get('crm_contact')->isEmpty()) {
134          $detail->set('crm_contact', $this->id());
135          $detail->save();
136        }
137      }
138
139    }
140  }
141
142  /**
143   * {@inheritdoc}
144   */
145  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
146    $fields = parent::baseFieldDefinitions($entity_type);
147
148    $fields['name'] = BaseFieldDefinition::create('string')
149      ->setRevisionable(TRUE)
150      ->setLabel(t('Name'))
151      ->setRequired(TRUE)
152      ->setSetting('max_length', 255)
153      ->setDisplayOptions('form', [
154        'type' => 'string_textfield',
155        'weight' => -5,
156      ])
157      ->setDisplayConfigurable('form', TRUE)
158      ->setDisplayOptions('view', [
159        'label' => 'hidden',
160        'type' => 'string',
161        'weight' => -5,
162      ])
163      ->setDisplayConfigurable('view', TRUE);
164
165    $fields['emails'] = BaseFieldDefinition::create('entity_reference')
166      ->setLabel(t('Emails'))
167      ->setRevisionable(TRUE)
168      ->setCardinality(-1)
169      ->setSetting('target_type', 'crm_contact_detail')
170      ->setSetting('handler_settings', ['target_bundles' => ['email']])
171      ->setDisplayConfigurable('form', TRUE)
172      ->setDisplayOptions('form', [
173        'type' => 'inline_entity_form_complex',
174        'weight' => 8,
175        'settings' => [
176          'allow_new' => TRUE,
177          'allow_existing' => FALSE,
178          'removed_reference' => InlineEntityFormComplex::REMOVED_DELETE,
179          'match_operator' => 'CONTAINS',
180          'allow_duplicate' => FALSE,
181          'form_mode' => 'default',
182          'override_labels' => TRUE,
183          'label_singular' => t('email'),
184          'label_plural' => t('emails'),
185          'collapsible' => FALSE,
186          'collapsed' => FALSE,
187          'revision' => TRUE,
188        ],
189      ])
190      ->setDisplayConfigurable('view', TRUE)
191      ->setDisplayOptions('view', [
192        'label' => 'hidden',
193        'type' => 'entity_reference_entity_view',
194        'weight' => -5,
195        'settings' => [
196          'view_mode' => 'default',
197          'link' => FALSE,
198        ],
199      ]);
200
201    $fields['telephones'] = BaseFieldDefinition::create('entity_reference')
202      ->setLabel(t('Telephones'))
203      ->setRevisionable(TRUE)
204      ->setCardinality(-1)
205      ->setSetting('target_type', 'crm_contact_detail')
206      ->setSetting('handler_settings', ['target_bundles' => ['telephone']])
207      ->setDisplayConfigurable('form', TRUE)
208      ->setDisplayOptions('form', [
209        'type' => 'inline_entity_form_complex',
210        'weight' => 9,
211        'settings' => [
212          'allow_new' => TRUE,
213          'allow_existing' => FALSE,
214          'removed_reference' => InlineEntityFormComplex::REMOVED_DELETE,
215          'match_operator' => 'CONTAINS',
216          'allow_duplicate' => FALSE,
217          'form_mode' => 'default',
218          'override_labels' => TRUE,
219          'label_singular' => t('telephone'),
220          'label_plural' => t('telephones'),
221          'collapsible' => FALSE,
222          'collapsed' => FALSE,
223          'revision' => TRUE,
224        ],
225      ])
226      ->setDisplayConfigurable('view', TRUE)
227      ->setDisplayOptions('view', [
228        'label' => 'hidden',
229        'type' => 'entity_reference_entity_view',
230        'weight' => -5,
231        'settings' => [
232          'view_mode' => 'default',
233          'link' => FALSE,
234        ],
235      ]);
236
237    $fields['addresses'] = BaseFieldDefinition::create('entity_reference')
238      ->setLabel('Addresses')
239      ->setRevisionable(TRUE)
240      ->setCardinality(-1)
241      ->setSetting('target_type', 'crm_contact_detail')
242      ->setSetting('handler_settings', ['target_bundles' => ['address']])
243      ->setDisplayConfigurable('form', TRUE)
244      ->setDisplayOptions('form', [
245        'type' => 'inline_entity_form_complex',
246        'weight' => 10,
247        'settings' => [
248          'allow_new' => TRUE,
249          'allow_existing' => FALSE,
250          'removed_reference' => InlineEntityFormComplex::REMOVED_DELETE,
251          'match_operator' => 'CONTAINS',
252          'allow_duplicate' => FALSE,
253          'form_mode' => 'default',
254          'override_labels' => TRUE,
255          'label_singular' => t('address'),
256          'label_plural' => t('addresses'),
257          'collapsible' => FALSE,
258          'collapsed' => FALSE,
259          'revision' => TRUE,
260        ],
261      ])
262      ->setDisplayConfigurable('view', TRUE)
263      ->setDisplayOptions('view', [
264        'label' => 'hidden',
265        'type' => 'entity_reference_entity_view',
266        'weight' => 0,
267        'settings' => [
268          'view_mode' => 'default',
269          'link' => FALSE,
270        ],
271      ]);
272
273    $fields['status'] = BaseFieldDefinition::create('boolean')
274      ->setLabel(t('Status'))
275      ->setDescription(t('A boolean indicating whether the contact is active.'))
276      ->setDefaultValue(TRUE)
277      ->setDisplayOptions('form', [
278        'type' => 'boolean_checkbox',
279        'settings' => [
280          'display_label' => TRUE,
281        ],
282        'weight' => 120,
283      ])
284      ->setSetting('on_label', 'Status')
285      ->setDisplayConfigurable('form', TRUE);
286
287    $fields['start_date'] = BaseFieldDefinition::create('datetime')
288      ->setLabel(t('Start Date'))
289      ->setDescription(t('When the contact starts.'))
290      ->setRevisionable(TRUE)
291      ->setSettings([
292        'datetime_type' => 'date',
293      ])
294      ->setDefaultValue('')
295      ->setDisplayConfigurable('form', TRUE)
296      ->setDisplayConfigurable('view', TRUE)
297      ->setRevisionable(TRUE);
298
299    $fields['end_date'] = BaseFieldDefinition::create('datetime')
300      ->setLabel(t('End Date'))
301      ->setDescription(t('When the contact ends.'))
302      ->setRevisionable(TRUE)
303      ->setSettings([
304        'datetime_type' => 'date',
305      ])
306      ->setDefaultValue('')
307      ->setDisplayConfigurable('form', TRUE)
308      ->setDisplayConfigurable('view', TRUE)
309      ->setRevisionable(TRUE);
310
311    $fields['age'] = BaseFieldDefinition::create('integer')
312      ->setLabel(t('Age'))
313      ->setDescription(t('The age of the contact.'))
314      ->setComputed(TRUE)
315      ->setClass(AgeFieldItemList::class)
316      ->setDisplayConfigurable('form', FALSE)
317      ->setDisplayConfigurable('view', TRUE);
318
319    $fields['created'] = BaseFieldDefinition::create('created')
320      ->setLabel(t('Created on'))
321      ->setDescription(t('The time that the contact was created.'))
322      ->setDisplayOptions('view', [
323        'label' => 'above',
324        'type' => 'timestamp',
325        'weight' => 20,
326      ])
327      ->setDisplayConfigurable('form', TRUE)
328      ->setDisplayOptions('form', [
329        'type' => 'datetime_timestamp',
330        'weight' => 20,
331      ])
332      ->setDisplayConfigurable('view', TRUE);
333
334    $fields['changed'] = BaseFieldDefinition::create('changed')
335      ->setLabel(t('Changed'))
336      ->setDescription(t('The time that the contact was last edited.'));
337
338    return $fields;
339  }
340
341}