improvements-2.x-dev/modules/improvements_taxonomy/improvements_taxonomy.module

modules/improvements_taxonomy/improvements_taxonomy.module
<?php

use Drupal\Core\Condition\ConditionManager;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\Checkboxes;
use Drupal\druhels\ArrayHelper;
use Drupal\druhels\TaxonomyHelper;
use Drupal\improvements\ImprovementsHelper;
use Drupal\pathauto\Form\PatternEditForm;
use Drupal\pathauto\PathautoPatternInterface;
use Drupal\taxonomy\TermForm;
use Drupal\taxonomy\TermInterface;

/**
 * Implements hook_entity_base_field_info().
 */
function improvements_taxonomy_entity_base_field_info(EntityTypeInterface $entity_type): array {
  if ($entity_type->id() == 'taxonomy_term') {
    $fields = [];

    $fields['stored_depth'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Depth'))
      ->setSetting('unsigned', TRUE);

    $fields['has_children'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Has chilren'))
      ->setDefaultValue(FALSE);

    return $fields;
  }

  return [];
}

/**
 * Implements hook_entity_base_field_info_alter().
 *
 * @param BaseFieldDefinition[] $fields
 *
 * @see \Drupal\taxonomy\Entity\Term::baseFieldDefinitions()
 */
function improvements_taxonomy_entity_base_field_info_alter(array &$fields, EntityTypeInterface $entity_type): void {
  if ($entity_type->id() == 'taxonomy_term') {
    $fields['name']->setDisplayConfigurable('view', TRUE);
  }
}

/**
 * Implements hook_entity_extra_field_info().
 */
function improvements_taxonomy_entity_extra_field_info(): array {
  $extra_fields = [];

  foreach (array_keys(\Drupal::service('entity_type.bundle.info')->getBundleInfo('taxonomy_term')) as $bundle) {
    /** @see improvements_taxonomy_form_taxonomy_term_form_alter() */
    $extra_fields['taxonomy_term'][$bundle]['form']['parent'] = [
      'label' => t('Parents'),
      'description' => t('Term parents.'),
      'weight' => 50,
    ];

    $extra_fields['taxonomy_term'][$bundle]['form']['revision_information'] = [
      'label' => t('Revision'),
      'description' => t('Revision information.'),
      'weight' => 50,
    ];
  }

  return $extra_fields;
}

/**
 * Implements hook_ENTITY_TYPE_presave(): taxonomy_term.
 */
function improvements_taxonomy_taxonomy_term_presave(TermInterface $term): void {
  // Set "stored_depth" field
  $term->set('stored_depth', TaxonomyHelper::getTermDepth($term));

  // Set "has_chilren" field
  if ($term->get('has_children')->isEmpty()) {
    $term->set('has_children', TaxonomyHelper::termHasChilds($term->id()));
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert(): taxonomy_term.
 */
function improvements_taxonomy_taxonomy_term_insert(TermInterface $term): void {
  // Set parent term "has_children" field value
  $parent_term = $term->get('parent')->entity; /** @var TermInterface $parent_term */
  if ($parent_term && !$parent_term->get('has_children')->value) {
    $parent_term->set('has_children', TRUE)->save();
  }
}

/**
 * Implements hook_ENTITY_TYPE_update(): taxonomy_term.
 */
function improvements_taxonomy_taxonomy_term_update(TermInterface $term): void {
  /** @noinspection All */
  $original_term = $term->original; /** @var TermInterface $original_term */

  // Manualy save children terms to run improvements_taxonomy_term_presave() and update "stored_depth" field
  $term_depth_is_changed = ($term->get('stored_depth')->value != $original_term->get('stored_depth')->value);
  if ($term_depth_is_changed || $original_term->get('stored_depth')->isEmpty()) {
    if ($term_direct_children = TaxonomyHelper::getDirectChildTerms($term->bundle(), $term->id(), TRUE)) {
      foreach ($term_direct_children as $children_term) {
        $children_term->save();
      }
    }
  }

  // Update parent terms "has_children" field
  $term_parent_items = $term->get('parent');
  $original_term_parent_items = $original_term->get('parent');
  $term_parent_is_changed = $term_parent_items->hasAffectingChanges($original_term_parent_items, $term_parent_items->getLangcode());

  if ($term_parent_is_changed) {
    // Update new parent terms
    if ($term_parent_items->entity) {
      foreach ($term_parent_items as $term_parent_item) {
        $parent_term = $term_parent_item->entity; /** @var TermInterface $parent_term */
        if (!$parent_term->get('has_children')->value) {
          $parent_term->set('has_children', TRUE)->save();
        }
      }
    }

    // Update old parent terms
    if ($original_term_parent_items->entity) {
      foreach ($original_term_parent_items as $original_term_parent_item) {
        $original_parent_term = $original_term_parent_item->entity; /** @var TermInterface $original_parent_term */
        $original_parent_term_has_children_new = TaxonomyHelper::termHasChilds($original_parent_term->id());
        if ($original_parent_term->get('has_children')->value != $original_parent_term_has_children_new) {
          $original_parent_term->set('has_children', $original_parent_term_has_children_new)->save();
        }
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_delete(): taxonomy_term.
 */
function improvements_taxonomy_taxonomy_term_delete(TermInterface $term): void {
  // Update parent term "has_children" field value
  $parent_term = $term->get('parent')->entity; /** @var TermInterface $parent_term */
  if ($parent_term && !TaxonomyHelper::termHasChilds($parent_term->id(), TRUE)) {
    $parent_term->set('has_children', FALSE)->save();
  }
}

/**
 * Implements hook_form_BASE_FORM_ID_alter(): taxonomy_term_form.
 *
 * @see \Drupal\taxonomy\TermForm::form()
 */
function improvements_taxonomy_form_taxonomy_term_form_alter(array &$form, FormStateInterface $form_state, $foo = NULL, $bar = NULL): void {
  $form_object = $form_state->getFormObject(); /** @var TermForm $form_object */
  $term = $form_object->getEntity(); /** @var TermInterface $term */

  // Autofocus to term "name" field
  if (isset($form['name'])) {
    $form['name']['widget']['0']['value']['#attributes']['autofocus'] = TRUE;
  }

  // Change "relations" item type from "details" to "container"
  $form['relations']['#type'] = 'container';

  if (isset($form['relations']['parent'])) {
    // "parent" field visibility
    $entity_form_display = EntityFormDisplay::load("taxonomy_term.{$term->bundle()}.default");
    if ($entity_form_display && !$entity_form_display->getComponent('parent')) {
      $form['relations']['parent']['#access'] = FALSE;
    }

    // Increase "parent" select size
    if (
      $form['relations']['parent']['#type'] == 'select' &&
      $form['relations']['parent']['#multiple'] &&
      count($form['relations']['parent']['#options']) > 15
    ) {
      $form['relations']['parent']['#size'] = 15;
    }
  }

  // Change text of submit button
  if ($term->isNew() && isset($form['actions']['submit'])) {
    $form['actions']['submit']['#value'] = t('Save and add more');
  }

  // Move "delete" button to end
  if (isset($form['actions']['delete'])) {
    $form['actions']['delete']['#weight'] = 100;
  }
}

/**
 * Implements hook_form_FORM_ID_alter(): taxonomy_overview_terms.
 */
function improvements_taxonomy_form_taxonomy_overview_terms_alter(array &$form, FormStateInterface $form_state): void {
  $form['actions']['reset_alphabetical']['#access'] = FALSE;

  // Add "ID" column
  $form['terms']['#header'] = ArrayHelper::insertAfter($form['terms']['#header'], 'term', ['tid' => t('ID')]);
  foreach (Element::children($form['terms']) as $key) {
    $tid = explode(':', $key)[1];
    $form['terms'][$key] = ArrayHelper::insertAfter($form['terms'][$key], 'term', [
      'tid' => [
        '#type' => 'item',
        '#markup' => $tid,
      ],
    ]);
  }
}

/**
 * Implements hook_entity_type_build().
 */
function improvements_taxonomy_entity_type_build(array &$entity_types): void {
  // See https://www.drupal.org/node/3043840
  if (isset($entity_types['taxonomy_term'])) {
    $entity_types['taxonomy_term']->set('enable_base_field_custom_preprocess_skipping', TRUE);
  }
}

/**
 * Implements hook_entity_type_alter().
 *
 * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
 */
function improvements_taxonomy_entity_type_alter(array &$entity_types): void {
  if (isset($entity_types['taxonomy_term']) && !$entity_types['taxonomy_term']->hasLinkTemplate('delete-multiple-form')) {
    $entity_types['taxonomy_term']->setLinkTemplate('delete-multiple-form', '/admin/structure/taxonomy/delete-terms');
  }
}

/**
 * Implements hook_token_info().
 */
function improvements_taxonomy_token_info(): array {
  $info = [];

  $info['tokens']['term']['parents_field'] = [
    'name' => t('Parents field value'),
    'description' => t('An array of all the term\'s parents field value, starting with the root.'),
    'type' => 'array',
    'dynamic' => TRUE,
  ];

  return $info;
}

/**
 * Implements hook_tokens().
 */
function improvements_taxonomy_tokens(string $type, array $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata): array {
  $replacements = [];

  // [term:*]
  if ($type == 'term' && !empty($data['term'])) {
    $term = $data['term']; /* @var TermInterface $term */
    $token_service = \Drupal::token();

    // [term:parents_field:*]
    if ($parents_field_tokens = $token_service->findWithPrefix($tokens, 'parents_field')) {
      foreach ($parents_field_tokens as $name => $original) {
        [$field_name, ] = explode(':', $name);
        $field_values = ImprovementsHelper::getTermAllParentsFieldValues($term->id(), $field_name);

        if ($array_tokens = $token_service->findWithPrefix($parents_field_tokens, $field_name)) {
          $replacements += $token_service->generate('array', $array_tokens, ['array' => $field_values], $options, $bubbleable_metadata);
        }
        else {
          $replacements[$original] = token_render_array($field_values, $options);
        }
      }
    }
  }

  return $replacements;
}

/**
 * Implements hook_form_FORM_ID_alter(): pathauto_pattern_form.
 */
function improvements_taxonomy_form_pathauto_pattern_form_alter(array &$form, FormStateInterface $form_state): void {
  $pathauto_patter_form_object = $form_state->getFormObject(); /** @var PatternEditForm $pathauto_patter_form_object */
  $pathauto_pattern_entity = $pathauto_patter_form_object->getEntity(); /** @var PathautoPatternInterface $pathauto_pattern_entity */

  if ($pathauto_pattern_entity->getType() == 'canonical_entities:taxonomy_term') {
    // Find term_depth condition
    $term_depth_condition = NULL;
    foreach ($pathauto_pattern_entity->getSelectionConditions() as $condition) {
      if ($condition->getPluginId() == 'term_depth') {
        $term_depth_condition = $condition;
        break;
      }
    }

    // Create term_depth condition if not exists
    if (!$term_depth_condition) {
      $condition_manager = \Drupal::service('plugin.manager.condition'); /** @var ConditionManager $condition_manager */
      $term_depth_condition = $condition_manager->createInstance('term_depth');
    }

    $form['pattern_container']['depth_condition'] = [
      '#type' => 'details',
      '#title' => t('Term depth condition'),
      '#tree' => TRUE,
    ];
    $form['pattern_container']['depth_condition'] = $term_depth_condition->buildConfigurationForm($form['pattern_container']['depth_condition'], $form_state);

    $form['#entity_builders'][] = 'improvements_taxonomy_form_pathauto_pattern_form_entity_builders';
  }
}

/**
 * Pathauto "pattern" form #entity_builders callback.
 *
 * @see improvements_taxonomy_form_pathauto_pattern_form_alter().
 */
function improvements_taxonomy_form_pathauto_pattern_form_entity_builders(string $entity_type, PathautoPatternInterface $pathauto_pattern, array &$form, FormStateInterface $form_state): void {
  $selected_depth = Checkboxes::getCheckedCheckboxes($form_state->getValue(['depth_condition', 'depth']));

  // Remove old condition
  foreach ($pathauto_pattern->getSelectionConditions() as $condition_id => $condition) {
    if ($condition->getPluginId() == 'term_depth') {
      $pathauto_pattern->removeSelectionCondition($condition_id);
    }
  }

  // Add new condition
  if ($selected_depth) {
    $pathauto_pattern->addSelectionCondition([
      'id' => 'term_depth',
      'depth' => $selected_depth,
      'negate' => FALSE,
    ]);
  }
}

/**
 * Implements hook_token_info_alter().
 */
function improvements_taxonomy_token_info_alter(array &$data): void {
  if (isset($data['tokens']['term']['parents'])) {
    $data['tokens']['term']['parents']['name'] = t('Parents names');
  }
}

/**
 * Implements hook_local_tasks_alter().
 */
function improvements_taxonomy_local_tasks_alter(array &$local_tasks): void {
  if (isset($local_tasks['entity.taxonomy_vocabulary.overview_form'])) {
    $local_tasks['entity.taxonomy_vocabulary.overview_form']['title'] = t('Terms');
  }
  if (isset($local_tasks['entity.taxonomy_vocabulary.edit_form'])) {
    $local_tasks['entity.taxonomy_vocabulary.edit_form']['title'] = t('Edit vocabulary');
  }
}

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

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