Code Coverage  | 
      ||||||||||
Lines  | 
       Functions and Methods  | 
       Classes and Traits  | 
      ||||||||
| Total |         | 
       100.00%  | 
       207 / 207  | 
               | 
       100.00%  | 
       3 / 3  | 
       CRAP |         | 
       100.00%  | 
       1 / 1  | 
      
| Contact |         | 
       100.00%  | 
       207 / 207  | 
               | 
       100.00%  | 
       3 / 3  | 
       11 |         | 
       100.00%  | 
       1 / 1  | 
      
| preSave |         | 
       100.00%  | 
       17 / 17  | 
               | 
       100.00%  | 
       1 / 1  | 
       4 | |||
| postSave |         | 
       100.00%  | 
       8 / 8  | 
               | 
       100.00%  | 
       1 / 1  | 
       6 | |||
| baseFieldDefinitions |         | 
       100.00%  | 
       182 / 182  | 
               | 
       100.00%  | 
       1 / 1  | 
       1 | |||
| 1 | <?php | 
| 2 | |
| 3 | declare(strict_types=1); | 
| 4 | |
| 5 | namespace Drupal\crm\Entity; | 
| 6 | |
| 7 | use Drupal\Core\Entity\Attribute\ContentEntityType; | 
| 8 | use Drupal\Core\Entity\EntityChangedTrait; | 
| 9 | use Drupal\Core\Entity\EntityPublishedTrait; | 
| 10 | use Drupal\Core\Entity\EntityStorageInterface; | 
| 11 | use Drupal\Core\Entity\EntityTypeInterface; | 
| 12 | use Drupal\Core\Entity\RevisionableContentEntityBase; | 
| 13 | use Drupal\Core\Entity\RevisionLogEntityTrait; | 
| 14 | use Drupal\Core\Entity\Routing\AdminHtmlRouteProvider; | 
| 15 | use Drupal\Core\Field\BaseFieldDefinition; | 
| 16 | use Drupal\Core\StringTranslation\TranslatableMarkup; | 
| 17 | use Drupal\crm\ContactAccessControlHandler; | 
| 18 | use Drupal\crm\ContactListBuilder; | 
| 19 | use Drupal\crm\CrmContactInterface; | 
| 20 | use Drupal\crm\Form\ContactForm; | 
| 21 | use Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormComplex; | 
| 22 | use Drupal\views\EntityViewsData; | 
| 23 | use Drupal\Core\Entity\ContentEntityDeleteForm; | 
| 24 | use 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 | )] | 
| 84 | class 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('primary_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' => 'primary_entity_reference_inline_form', | 
| 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' => 'primary_entity_reference_entity_view', | 
| 194 | 'weight' => -5, | 
| 195 | 'settings' => [ | 
| 196 | 'view_mode' => 'default', | 
| 197 | 'link' => FALSE, | 
| 198 | ], | 
| 199 | ]); | 
| 200 | |
| 201 | $fields['telephones'] = BaseFieldDefinition::create('primary_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' => 'primary_entity_reference_inline_form', | 
| 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' => 'primary_entity_reference_entity_view', | 
| 230 | 'weight' => -5, | 
| 231 | 'settings' => [ | 
| 232 | 'view_mode' => 'default', | 
| 233 | 'link' => FALSE, | 
| 234 | ], | 
| 235 | ]); | 
| 236 | |
| 237 | $fields['addresses'] = BaseFieldDefinition::create('primary_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' => 'primary_entity_reference_inline_form', | 
| 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' => 'primary_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 | } |