taxonomy_manager-2.0.3/modules/taxonomy_manager_merge/src/Form/MergeTermsForm.php

modules/taxonomy_manager_merge/src/Form/MergeTermsForm.php
<?php

declare(strict_types=1);

namespace Drupal\taxonomy_manager_merge\Form;

use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\taxonomy\VocabularyInterface;
use Drupal\taxonomy_manager\Form\TaxonomyManagerForm;
use Drupal\term_merge\Form\MergeTerms;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form for merging the selected terms into a target term.
 */
class MergeTermsForm extends MergeTerms {

  use StringTranslationTrait;

  /**
   * The vocabulary.
   *
   * @var \Drupal\taxonomy\VocabularyInterface
   */
  protected VocabularyInterface $vocabulary;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected ModuleHandlerInterface $moduleHandler;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected Connection $database;

  /**
   * Constructs a MergeTermsForm object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity manager service.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempStoreFactory
   *   The private temporary storage factory service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
   *   The module handler.
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection.
   */
  public function __construct(
    EntityTypeManagerInterface $entityTypeManager,
    PrivateTempStoreFactory $tempStoreFactory,
    ModuleHandlerInterface $moduleHandler,
    Connection $database,
  ) {
    parent::__construct($entityTypeManager, $tempStoreFactory, $moduleHandler);
    $this->moduleHandler = $moduleHandler;
    $this->database = $database;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): MergeTermsForm {
    // @phpstan-ignore-next-line
    return new static(
      $container->get('entity_type.manager'),
      $container->get('tempstore.private'),
      $container->get('module_handler'),
      $container->get('database')
    );
  }

  /**
   * Form constructor.
   *
   * @param array $form
   *   Form render array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   * @param \Drupal\taxonomy\VocabularyInterface|null $taxonomy_vocabulary
   *   Selected terms.
   * @param array $selected_terms
   *   Selected terms.
   *
   * @return array
   *   Return render array of form or nothing if term_merge module not exists.
   */
  public function buildForm(array $form, FormStateInterface $form_state, ?VocabularyInterface $taxonomy_vocabulary = NULL, array $selected_terms = []): array {
    $form = parent::buildForm($form, $form_state, $taxonomy_vocabulary);
    if (is_null($taxonomy_vocabulary)) {
      return $form;
    }

    // We still need a private storage.
    $form_state->disableCache();
    $this->vocabulary = $taxonomy_vocabulary;

    $form['description'] = [
      '#type' => 'markup',
      '#markup' => $this->t('Select terms to merge'),
      '#weight' => -1,
    ];
    $form['terms']['#ajax'] = [
      'url' => Url::fromRoute(
        'taxonomy_manager_merge.admin_vocabulary.merge_terms',
        [
          'taxonomy_vocabulary' => $taxonomy_vocabulary->id(),
        ],
      ),
      'options' => [
        'query' => [
          FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
        ],
      ],
      'event' => 'change',
      'callback' => '::rebuildExistingTermsOptions',
      'wrapper' => 'existing-terms',
      'disable-refocus' => FALSE,
    ];

    /** @var array $selected_terms */
    $selected_terms = count($selected_terms) > 0 ? $selected_terms : (!empty($form_state->getUserInput()['terms']) ? $form_state->getUserInput()['terms'] : []);
    $form['terms']['#default_value'] = $selected_terms;
    // Limit options due to memory issues on large vocabularies.
    $form['terms']['#options'] = $this->getSelectedOrAllTermOptions($taxonomy_vocabulary, $selected_terms);

    // Optionally add all child terms to the target term,
    // that means that child terms will get new parent.
    $form['add_child_terms_to_target'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Add child terms to target'),
      '#description' => $this->t('Allow all sub children to be merged into the target term otherwise child terms gets a new parent.'),
    ];

    $form['terms_to_synonym'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Add source term as synonym'),
      '#description' => $this->t('Selected terms titles will get moved to the target term.'),
    ];

    $form['description']['#markup'] = $this->t('Enter a new term or select an existing term to merge into.');

    $form['new'] = [
      '#type' => 'textfield',
      '#title' => $this->t('New term'),
    ];

    $form['existing'] = [
      '#type' => 'entity_autocomplete',
      '#title' => $this->t('Existing term'),
      '#target_type' => 'taxonomy_term',
      '#selection_handler' => 'default:filter_existing_terms',
      '#selection_settings' => [
        'target_bundles' => [
          $taxonomy_vocabulary->id(),
        ],
      ],
      '#empty_option' => $this->t('Select an existing term'),
      '#prefix' => '<div id="existing-terms">',
      '#suffix' => '</div>',
    ];

    if (count($selected_terms) > 0) {
      $form['existing']['#selection_settings']['filter'] = ['tid' => $selected_terms];
    }

    return $form;
  }

  /**
   * Rebuild existing element with new data.
   *
   * @param array $form
   *   Form render array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   *
   * @return array
   *   Returns existing terms element with new data.
   */
  public function rebuildExistingTermsOptions(array $form, FormStateInterface $form_state): array {
    return $form['existing'];
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    parent::validateForm($form, $form_state);

    $new = !empty($form_state->getValue('new'));
    $existing = !empty($form_state->getValue('existing'));

    if ($new !== $existing) {
      return;
    }

    $form_state->setErrorByName('existing', (string) $this->t('You must either select an existing term or enter a new term.'));
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $term_store = $this->tempStoreFactory->get('term_merge');
    /** @var array $selected_terms */
    $selected_terms = $form_state->getValue('terms', []);
    if (count($selected_terms) > 0) {
      $term_store->set('terms', $selected_terms);
    }

    if (!empty($form_state->getValue('new'))) {
      $term_store->set('target', $form_state->getValue('new'));
    }

    if (!empty($form_state->getValue('existing'))) {
      $term = $this->termStorage->load($form_state->getValue('existing'));
      $term_store->set('target', $term);
    }

    if (!empty($form_state->getValue('add_child_terms_to_target')) || $form_state->hasValue('add_child_terms_to_target')) {
      $term_store->set('merge_children', $form_state->getValue('add_child_terms_to_target'));
    }

    if (!empty($form_state->getValue('terms_to_synonym')) || $form_state->hasValue('terms_to_synonym')) {
      $term_store->set('terms_to_synonym', $form_state->getValue('terms_to_synonym'));
    }

    $route_name = 'entity.taxonomy_vocabulary.merge_confirm';
    $route_parameters = [
      'taxonomy_vocabulary' => $this->vocabulary->id(),
    ];
    // We have to specify destination to redirect back to the vocabulary.
    // It can happen due to internal redirect from the term merge module to
    // taxonomy list overview.
    $destination = Url::fromRoute('taxonomy_manager.admin_vocabulary', ['taxonomy_vocabulary' => $this->vocabulary->id()]);
    $form_state->setRedirect($route_name, $route_parameters, ['query' => ['destination' => $destination->toString()]]);
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'taxonomy_manager_merge_form';
  }

  /**
   * {@inheritdoc}
   */
  protected function getTermOptions(VocabularyInterface $vocabulary) {
    // Parent method is overridden with a faster implementation.
    // @see \Drupal\taxonomy_manager\Form\MergeTermsForm::getSelectedOrAllTermOptions()
    return [];
  }

  /**
   * Builds a list of all or selected terms in this vocabulary.
   *
   * @param \Drupal\taxonomy\VocabularyInterface $vocabulary
   *   The vocabulary.
   * @param array $selected_terms
   *   The selected terms to merge.
   * @param int $limit
   *   The limit of terms to load after which is used only selected terms.
   *
   * @return string[]
   *   An array of taxonomy term labels keyed by their id.
   */
  protected function getSelectedOrAllTermOptions(VocabularyInterface $vocabulary, array $selected_terms, int $limit = 1000): array {
    $options = [];
    $query = $this->database->select('taxonomy_term_field_data', 't')
      ->fields('t', ['tid', 'name'])
      ->condition('vid', $vocabulary->id())
      ->orderBy('name');
    $total = (clone $query)->countQuery()->execute()->fetchField();

    if ($total < $limit) {
      $options = $query
        ->execute()
        ->fetchAllKeyed();
    }
    if ($total > $limit) {
      $options = $query
        ->condition('tid', $selected_terms, 'IN')
        ->execute()
        ->fetchAllKeyed();
    }
    asort($options);

    return $options;
  }

  /**
   * AJAX callback handler for merge terms to a target term.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state of the current (parent) form.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   The ajax response.
   */
  public static function mergeTermsFormCallback(array $form, FormStateInterface $form_state) {
    return TaxonomyManagerForm::modalHelperStatic($form_state, self::class, 'taxonomy_manager_merge.admin_vocabulary.merge_terms', (string) t('Merge terms'));
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc