View source
<?php
namespace Drupal\crm_core_contact\Plugin\Action;
use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Form\FormStateInterface;
use Drupal\crm_core_activity\Entity\Activity;
use Drupal\crm_core_contact\Entity\Contact;
use Drupal\relation\Entity\Relation;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\path_alias\PathAliasStorage;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\StringTranslation\TranslationManager;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Render\Renderer;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Messenger\MessengerInterface;
class MergeContactsAction extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
protected $pathAliasStorage;
protected $moduleHandler;
protected $translationManager;
protected $entityTypeManager;
protected $entityFieldManager;
protected $renderer;
protected $messenger;
public function __construct(array $configuration, $plugin_id, $plugin_definition, PathAliasStorage $path_alias_storage, ModuleHandler $module_handler, TranslationManager $translation_manager, EntityTypeManager $entity_type_manager, EntityFieldManager $entity_field_manager, Renderer $renderer, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->pathAliasStorage = $path_alias_storage;
$this->moduleHandler = $module_handler;
$this->translationManager = $translation_manager;
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->renderer = $renderer;
$this->messenger = $messenger;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('path.alias_storage'), $container
->get('module_handler'), $container
->get('string_translation'), $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('renderer'), $container
->get('messenger'));
}
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $return_as_object ? AccessResult::allowed() : AccessResult::allowed()
->isAllowed();
}
public function executeMultiple(array $objects) {
$crm_core_activity_storage = $this->entityTypeManager
->getStorage('crm_core_activity');
$crm_core_activity_query = $storage
->getQuery();
$relation_storage = $this->entityTypeManager
->getStorage('relation');
$relation_query = $storage
->getQuery();
$primary_contact = reset($objects);
foreach ($objects as $cid => $contact) {
if ($contact
->id() == $this->configuration['data']['contact_id']) {
$primary_contact = $contact;
unset($objects[$cid]);
break;
}
}
unset($this->configuration['data']['contact_id']);
$wrappers = [];
foreach ($objects as $contact) {
$wrappers[$contact
->id()] = $contact;
}
foreach ($this->configuration['data'] as $field_name => $contact_id) {
if ($primary_contact
->id() != $contact_id) {
$primary_contact
->set($field_name, $wrappers[key($contact_id)]
->get($field_name)
->getValue());
}
}
$primary_contact
->save();
foreach (array_keys($wrappers) as $contact_id) {
$this->pathAliasStorage
->save('/crm-core/contact/' . $primary_contact
->id(), '/crm-core/contact/' . $contact_id);
if ($this->moduleHandler
->moduleExists('crm_core_activity')) {
$activities = $crm_core_activity_query
->condition('activity_participants.target_id', $contact_id)
->condition('activity_participants.target_type', 'crm_core_contact')
->execute();
if (is_array($activities)) {
foreach (Activity::loadMultiple($activities) as $activity) {
foreach ($activity->activity_participants as $delta => $participant) {
if ($participant->target_id == $contact_id) {
$activity
->get('activity_participants')[$delta]
->setValue($primary_contact);
}
}
$activity
->save();
}
}
}
if ($this->moduleHandler
->moduleExists('relation')) {
$relations = $relation_query
->condition('endpoints.entity_type', 'crm_core_contact', '=')
->condition('endpoints.entity_id', $contact_id, '=')
->execute();
foreach ($relations as $relation_info) {
$endpoints = [
[
'entity_type' => 'crm_core_contact',
'entity_id' => $primary_contact
->id(),
],
];
$relation = Relation::load($relation_info);
foreach ($relation->endpoints as $endpoint) {
if ($endpoint->entity_id != $contact_id) {
$endpoints[] = [
'entity_type' => $endpoint->entity_type,
'entity_id' => $endpoint->entity_id,
];
}
}
$new_relation = Relation::create([
'relation_type' => $relation->relation_type->target_id,
'endpoints' => $endpoints,
]);
$new_relation
->save();
}
}
}
$count = count($wrappers);
$singular = '%contacts contact merged to %dest.';
$plural = '%contacts contacts merged to %dest.';
$contacts_label = array_map(function ($contact) {
return $contact
->label();
}, $wrappers);
$message = $this->translationManager
->formatPlural($count, $singular, $plural, [
'%contacts' => implode(', ', $contacts_label),
'%dest' => $primary_contact
->label(),
]);
$this->entityTypeManager
->getStorage('crm_core_contact')
->delete($wrappers);
$this->messenger
->addMessage($message);
}
public function execute($object = NULL) {
$this
->executeMultiple([
$object,
]);
}
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
$primary_contact = array_filter($form_state
->getValue('table')['contact_id']);
if (empty($primary_contact)) {
$form_state
->setError($form['table']['contact_id'], $this
->t('You must select primary contact in table header!'));
}
if (count($primary_contact) > 1) {
$form_state
->setError($form['table']['contact_id'], $this
->t('Supplied more than one primary contact!'));
}
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = [];
$selected_contacts = Contact::loadMultiple($form_state
->getValue('selection'));
$selected_contacts_ids = array_map(function ($contact) {
return $contact
->id();
}, $selected_contacts);
$contact_types = array_map(function ($contact) {
return $contact->type->target_id;
}, $selected_contacts);
if (count(array_unique($contact_types)) != 1) {
$this->messenger
->addMessage($this
->t('You should select contacts of one type to be able to merge them!'), 'error');
$form_state
->setRedirect('entity.crm_core_contact.collection');
}
else {
$form['table'] = [
'#type' => 'table',
'#tree' => TRUE,
'#selected' => $selected_contacts_ids,
];
$header['field_name'] = [
'#markup' => $this
->t('Field name\\Contact'),
];
foreach ($selected_contacts as $contact) {
$header[$contact->contact_id->value] = [
'#type' => 'radio',
'#title' => $contact
->label(),
];
}
$form['table']['contact_id'] = $header;
$field_instances = $this->entityFieldManager
->getFieldDefinitions('crm_core_contact', reset($contact_types));
unset($field_instances['contact_id']);
foreach ($field_instances as $field_name => $field_instance) {
$form['table'][$field_name] = [];
$form['table'][$field_name]['field_name'] = [
'#markup' => $field_instance
->getLabel(),
];
foreach ($selected_contacts as $contact) {
$field_value = [
'#markup' => '',
];
$contact_field_value = $contact
->get($field_name);
if (isset($contact_field_value)) {
$field_value_render = $contact_field_value
->view('full');
$field_value_rendered = $this->renderer
->render($field_value_render);
if (!empty($field_value_rendered)) {
$field_value = [
'#type' => 'radio',
'#title' => $field_value_rendered,
];
}
}
$form['table'][$field_name][$contact->contact_id->value] = $field_value;
}
}
}
$form['#attached']['library'][] = 'crm_core_contact/drupal.crm_core_contact.merge-contacts';
return $form;
}
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$data = [
'contact_id' => array_shift(array_keys(array_filter($form_state
->getValue('table')['contact_id']))),
];
unset($form_state
->getValue('table')['contact_id']);
foreach ($form_state
->getValue('table') as $field_name => $selection) {
$data[$field_name] = array_shift(array_keys(array_filter($selection)));
}
$this->configuration['data'] = array_filter($data);
}
}