class MergeContactsAction in CRM Core 8
Same name and namespace in other branches
- 8.3 modules/crm_core_contact/src/Plugin/Action/MergeContactsAction.php \Drupal\crm_core_contact\Plugin\Action\MergeContactsAction
- 8.2 modules/crm_core_contact/src/Plugin/Action/MergeContactsAction.php \Drupal\crm_core_contact\Plugin\Action\MergeContactsAction
Merges 2 or more contacts.
Plugin annotation
@Action(
id = "merge_contacts_action",
label = @Translation("Merge contacts"),
type = "crm_core_contact"
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\Core\Action\ActionBase implements ActionInterface
- class \Drupal\Core\Action\ConfigurableActionBase implements ConfigurableInterface, ConfigurablePluginInterface, DependentPluginInterface, PluginFormInterface
- class \Drupal\crm_core_contact\Plugin\Action\MergeContactsAction implements ContainerFactoryPluginInterface
- class \Drupal\Core\Action\ConfigurableActionBase implements ConfigurableInterface, ConfigurablePluginInterface, DependentPluginInterface, PluginFormInterface
- class \Drupal\Core\Action\ActionBase implements ActionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of MergeContactsAction
File
- modules/
crm_core_contact/ src/ Plugin/ Action/ MergeContactsAction.php, line 31
Namespace
Drupal\crm_core_contact\Plugin\ActionView source
class MergeContactsAction extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
/**
* The path alias storage.
*
* @var \Drupal\Core\Path\AliasStorage
*/
protected $pathAliasStorage;
/**
* The module handler.
*
* @var \Drupal\Core\Mail\MailManagerInterface
*/
protected $moduleHandler;
/**
* The entity query.
*
* @var \Drupal\Core\Entity\Query\QueryFactory
*/
protected $entityQuery;
/**
* The translation manager.
*
* @var \Drupal\Core\StringTranslation\TranslationManager
*/
protected $translationManager;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManager
*/
protected $entityFieldManager;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\Renderer
*/
protected $renderer;
/**
* Constructs a EmailAction object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Path\AliasStorage $path_alias_storage
* The path alias storage.
* @param \Drupal\Core\Extension\ModuleHandler $module_handler
* The module handler.
* @param \Drupal\Core\Entity\Query\QueryFactory $entity_query
* The entity query.
* @param \Drupal\Core\StringTranslation\TranslationManager $translation_manager
* The translation manager.
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Render\Renderer $renderer
* The renderer service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, AliasStorage $path_alias_storage, ModuleHandler $module_handler, QueryFactory $entity_query, TranslationManager $translation_manager, EntityTypeManager $entity_type_manager, EntityFieldManager $entity_field_manager, Renderer $renderer) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->pathAliasStorage = $path_alias_storage;
$this->moduleHandler = $module_handler;
$this->entityQuery = $entity_query;
$this->translationManager = $translation_manager;
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
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('entity.query'), $container
->get('string_translation'), $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('renderer'));
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $return_as_object ? AccessResult::allowed() : AccessResult::allowed()
->isAllowed();
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $objects) {
$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;
}
// Updating contact fields from other selected contacts.
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) {
// Creating path aliases for contacts that will be deleted.
$this->pathAliasStorage
->save('/crm-core/contact/' . $primary_contact
->id(), '/crm-core/contact/' . $contact_id);
if ($this->moduleHandler
->moduleExists('crm_core_activity')) {
// Replacing participant in existing activities.
$query = $this->entityQuery
->get('crm_core_activity');
$activities = $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')) {
// Replacing existing relations for contacts been deleted with new ones.
$query = $this->entityQuery
->get('relation');
$relations = $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);
drupal_set_message($message);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this
->executeMultiple([
$object,
]);
}
/**
* {@inheritdoc}
*/
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!'));
}
}
/**
* {@inheritdoc}
*/
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);
// Lets check contacts type, it should be unique.
$contact_types = array_map(function ($contact) {
return $contact->type->target_id;
}, $selected_contacts);
// All selected contacts have same type.
if (count(array_unique($contact_types)) != 1) {
drupal_set_message($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,
];
// Creating header.
$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);
// Some fields can provide empty markup.
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;
}
/**
* {@inheritdoc}
*/
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);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ConfigurableActionBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
1 |
ConfigurableActionBase:: |
public | function |
Gets default configuration for this plugin. Overrides ConfigurableInterface:: |
8 |
ConfigurableActionBase:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
ConfigurableActionBase:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
MergeContactsAction:: |
protected | property | The entity field manager. | |
MergeContactsAction:: |
protected | property | The entity query. | |
MergeContactsAction:: |
protected | property | The entity type manager. | |
MergeContactsAction:: |
protected | property | The module handler. | |
MergeContactsAction:: |
protected | property | The path alias storage. | |
MergeContactsAction:: |
protected | property | The renderer service. | |
MergeContactsAction:: |
protected | property | The translation manager. | |
MergeContactsAction:: |
public | function |
Checks object access. Overrides ActionInterface:: |
|
MergeContactsAction:: |
public | function |
Form constructor. Overrides PluginFormInterface:: |
|
MergeContactsAction:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
MergeContactsAction:: |
public | function |
Executes the plugin. Overrides ExecutableInterface:: |
|
MergeContactsAction:: |
public | function |
Executes the plugin for an array of objects. Overrides ActionBase:: |
|
MergeContactsAction:: |
public | function |
Form submission handler. Overrides PluginFormInterface:: |
|
MergeContactsAction:: |
public | function |
Form validation handler. Overrides ConfigurableActionBase:: |
|
MergeContactsAction:: |
public | function |
Constructs a EmailAction object. Overrides ConfigurableActionBase:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |