You are here

public function RedhenDedupeMergeForm::buildForm in RedHen CRM 8

Form constructor.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Return value

array The form structure.

Overrides FormInterface::buildForm

File

modules/redhen_dedupe/src/Form/RedhenDedupeMergeForm.php, line 34

Class

RedhenDedupeMergeForm
Form controller for Dedupe merge tool.

Namespace

Drupal\redhen_dedupe\Form

Code

public function buildForm(array $form, FormStateInterface $form_state, $entity_ids = NULL) {

  // Load the entities we want to merge:
  $entity_ids = explode(',', $entity_ids);
  $contacts = \Drupal::entityTypeManager()
    ->getStorage('redhen_contact')
    ->loadMultiple($entity_ids);
  $master_options = [];

  // Loop through the entities to build out our master entity options:
  foreach ($contacts as $ent_id => $entity) {
    $updated = \Drupal::service('date.formatter')
      ->format($entity
      ->getChangedTime(), 'short');
    $master_options[$ent_id] = $this
      ->t('@name (Updated: @date)', [
      '@date' => $updated,
      '@name' => $entity
        ->label(),
    ]);
  }

  // Form field to select a merge master entity.
  $form['master'] = [
    '#type' => 'radios',
    '#title' => t('Master Contact'),
    '#default_value' => key($master_options),
    '#required' => TRUE,
    '#options' => $master_options,
    '#description' => $this
      ->t('Choose a contact to merge the other contacts into.'),
    '#weight' => 0,
    '#ajax' => [
      'callback' => '\\Drupal\\redhen_dedupe\\Form\\RedhenDedupeMergeForm::redhenDedupeMergeFormCallback',
      'wrapper' => 'redhen_dedupe_merge_data',
    ],
  ];
  $merge_data_attributes = new Attribute();
  $merge_data_attributes['id'] = 'redhen_dedupe_merge_data';
  $form['merge_data'] = [
    '#type' => 'container',
    '#attributes' => $merge_data_attributes,
  ];
  $master_id = $form_state
    ->getValue([
    'master',
  ]) ? (int) $form_state
    ->getValue([
    'master',
  ]) : key($master_options);
  $merge_data =& $form['merge_data'];
  $view_builder = \Drupal::entityTypeManager()
    ->getViewBuilder($entity
    ->getEntityTypeId());
  $preview = $view_builder
    ->view($contacts[$master_id]);
  $merge_data['contact_preview'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Master contact details'),
    'preview' => [
      '#markup' => render($preview),
    ],
  ];

  // Initialize our table header:
  $table_header = [
    $this
      ->t('Field Name'),
  ];

  // Loop through the entities to build out our table headers and master
  // entity options:
  foreach ($contacts as $ent_id => $contact) {
    $updated = \Drupal::service('date.formatter')
      ->format($contact
      ->getChangedTime(), 'short');
    $header_data = [
      '@date' => $updated,
      '@name' => $contact
        ->label(),
      '@bundle' => $contact
        ->bundle(),
      '@master' => $ent_id == $master_id ? t('Master') . ': ' : '',
    ];
    $table_header[$ent_id] = [
      'data' => $this
        ->t('@master@name (@bundle)<br/>Last Updated: @date', $header_data),
      'class' => [
        $ent_id == $master_id ? 'redhen-dedupe-master-col' : 'redhen-dedupe-col',
      ],
    ];
  }

  // Pass along the entity ID options & master ID to the form handler:
  $form_state
    ->set([
    'contacts',
  ], $contacts);

  // Now we build our merge selector form fields:
  $merge_data['values'] = [
    '#theme' => 'redhen_dedupe_form_table',
    '#tree' => TRUE,
    '#header' => $table_header,
  ];
  $bundles = \Drupal::service('entity_type.bundle.info')
    ->getBundleInfo('redhen_contact');
  $info = [];
  foreach (array_keys($bundles) as $bundle) {
    $info[$bundle] = \Drupal::service('entity_field.manager')
      ->getFieldDefinitions('redhen_contact', $bundle);
  }

  // Loop through each property and build a form element for it. The form
  // element will be placed into a table in redhen_dedupe_form_table:
  foreach ($info as $bundle => $field_definition) {
    foreach ($field_definition as $name => $field) {

      // Skip property if it does not exist on the master record.
      if (!isset($entity->{$name})) {
        continue;
      }

      // Call a helper function to determine we want to merge this field:
      if ($this
        ->redhenDedupeBaseFieldMergeable($field)) {
        if ($this
          ->redhenDedupeFieldIsMultivalue($field)) {
          $merge_data['values'][$name] = [
            '#type' => 'checkboxes',
            '#title' => Xss::filter($field
              ->getLabel()),
            '#options' => [],
          ];
        }
        else {
          $merge_data['values'][$name] = [
            '#type' => 'radios',
            '#title' => $field
              ->getLabel(),
            '#options' => [],
          ];
        }
        $options =& $merge_data['values'][$name]['#options'];

        // Loop through each contact to build a row element/radio button:
        foreach ($contacts as $ent_id => $contact) {

          // We do some work to figure out what kind of field we are dealing
          // with, and set our values and displays appropriately. The
          // important factors are if it's a field or not, and whether it has
          // a setter/getter callback that we should be using.
          $in_bundle = $bundle == $contact
            ->bundle();
          if (!$in_bundle) {
            $options[$ent_id] = REDHEN_DEDUPE_NOT_APPLICABLE;
            continue;
          }

          // Set the default to match the Master record:
          if ($ent_id === $master_id) {
            $merge_data['values'][$name]['#default_value'] = $merge_data['values'][$name]['#type'] == 'radios' ? $ent_id : [
              $ent_id,
            ];
          }
          $options[$ent_id] = $this
            ->redhenDedupeOptionLabel($contact, $name);
        }
      }
    }
  }

  // Exclude properties that are all the same from the merge form.
  foreach (Element::children($merge_data['values']) as $name) {
    $left = array_unique($merge_data['values'][$name]['#options']);

    // Filter out any remaining items that are not applicable.
    $left = array_filter($left, function ($item) {
      return $item !== REDHEN_DEDUPE_NOT_APPLICABLE;
    });
    if (empty($left) || count($left) === 1) {
      unset($merge_data['values'][$name]);
      continue;
    }
  }
  $related_types = [];
  if (\Drupal::moduleHandler()
    ->moduleExists('redhen_note')) {
    $related_types['redhen_note'] = t('Notes');
  }
  if (\Drupal::moduleHandler()
    ->moduleExists('redhen_engagement')) {
    $related_types['redhen_engagement'] = t('Engagement Scores');
  }
  if (\Drupal::moduleHandler()
    ->moduleExists('redhen_membership')) {
    $related_types['redhen_membership'] = t('Memberships');
  }
  if (\Drupal::moduleHandler()
    ->moduleExists('redhen_connection')) {
    $related_types['redhen_connection'] = t('Connections/Affiliations');
  }
  if (count($related_types) > 0) {
    $form['related_entities'] = [
      '#type' => 'checkboxes',
      '#title' => t('Move items attached to old records to Master record:'),
      '#options' => $related_types,
      '#default_value' => array_keys($related_types),
    ];
  }
  $form['submit'] = [
    '#type' => 'submit',
    '#value' => t('Merge'),
  ];
  return $form;
}