3 namespace Drupal\taxonomy;
5 use Drupal\Core\Entity\ContentEntityForm;
6 use Drupal\Core\Form\FormStateInterface;
9 * Base for handler for taxonomy term edit forms.
13 class TermForm extends ContentEntityForm {
18 public function form(array $form, FormStateInterface $form_state) {
19 $term = $this->entity;
20 $vocab_storage = $this->entityManager->getStorage('taxonomy_vocabulary');
21 $taxonomy_storage = $this->entityManager->getStorage('taxonomy_term');
22 $vocabulary = $vocab_storage->load($term->bundle());
24 $parent = array_keys($taxonomy_storage->loadParents($term->id()));
25 $form_state->set(['taxonomy', 'parent'], $parent);
26 $form_state->set(['taxonomy', 'vocabulary'], $vocabulary);
28 $form['relations'] = [
30 '#title' => $this->t('Relations'),
31 '#open' => $vocabulary->getHierarchy() == VocabularyInterface::HIERARCHY_MULTIPLE,
35 // \Drupal\taxonomy\TermStorageInterface::loadTree() and
36 // \Drupal\taxonomy\TermStorageInterface::loadParents() may contain large
37 // numbers of items so we check for taxonomy.settings:override_selector
38 // before loading the full vocabulary. Contrib modules can then intercept
39 // before hook_form_alter to provide scalable alternatives.
40 if (!$this->config('taxonomy.settings')->get('override_selector')) {
42 if (!$term->isNew()) {
43 $parent = array_keys($taxonomy_storage->loadParents($term->id()));
44 $children = $taxonomy_storage->loadTree($vocabulary->id(), $term->id());
46 // A term can't be the child of itself, nor of its children.
47 foreach ($children as $child) {
48 $exclude[] = $child->tid;
50 $exclude[] = $term->id();
53 $tree = $taxonomy_storage->loadTree($vocabulary->id());
54 $options = ['<' . $this->t('root') . '>'];
59 foreach ($tree as $item) {
60 if (!in_array($item->tid, $exclude)) {
61 $options[$item->tid] = str_repeat('-', $item->depth) . $item->name;
65 $form['relations']['parent'] = [
67 '#title' => $this->t('Parent terms'),
68 '#options' => $options,
69 '#default_value' => $parent,
74 $form['relations']['weight'] = [
75 '#type' => 'textfield',
76 '#title' => $this->t('Weight'),
78 '#default_value' => $term->getWeight(),
79 '#description' => $this->t('Terms are displayed in ascending order by weight.'),
85 '#value' => $vocabulary->id(),
90 '#value' => $term->id(),
93 return parent::form($form, $form_state);
99 public function validateForm(array &$form, FormStateInterface $form_state) {
100 parent::validateForm($form, $form_state);
102 // Ensure numeric values.
103 if ($form_state->hasValue('weight') && !is_numeric($form_state->getValue('weight'))) {
104 $form_state->setErrorByName('weight', $this->t('Weight value must be numeric.'));
111 public function buildEntity(array $form, FormStateInterface $form_state) {
112 $term = parent::buildEntity($form, $form_state);
114 // Prevent leading and trailing spaces in term names.
115 $term->setName(trim($term->getName()));
117 // Assign parents with proper delta values starting from 0.
118 $term->parent = array_keys($form_state->getValue('parent'));
126 public function save(array $form, FormStateInterface $form_state) {
127 $term = $this->entity;
129 $result = $term->save();
131 $edit_link = $term->link($this->t('Edit'), 'edit-form');
132 $view_link = $term->link($term->getName());
135 $this->messenger()->addStatus($this->t('Created new term %term.', ['%term' => $view_link]));
136 $this->logger('taxonomy')->notice('Created new term %term.', ['%term' => $term->getName(), 'link' => $edit_link]);
139 $this->messenger()->addStatus($this->t('Updated term %term.', ['%term' => $view_link]));
140 $this->logger('taxonomy')->notice('Updated term %term.', ['%term' => $term->getName(), 'link' => $edit_link]);
144 $current_parent_count = count($form_state->getValue('parent'));
145 $previous_parent_count = count($form_state->get(['taxonomy', 'parent']));
146 // Root doesn't count if it's the only parent.
147 if ($current_parent_count == 1 && $form_state->hasValue(['parent', 0])) {
148 $current_parent_count = 0;
149 $form_state->setValue('parent', []);
152 // If the number of parents has been reduced to one or none, do a check on the
153 // parents of every term in the vocabulary value.
154 $vocabulary = $form_state->get(['taxonomy', 'vocabulary']);
155 if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) {
156 taxonomy_check_vocabulary_hierarchy($vocabulary, $form_state->getValues());
158 // If we've increased the number of parents and this is a single or flat
159 // hierarchy, update the vocabulary immediately.
160 elseif ($current_parent_count > $previous_parent_count && $vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE) {
161 $vocabulary->setHierarchy($current_parent_count == 1 ? VocabularyInterface::HIERARCHY_SINGLE : VocabularyInterface::HIERARCHY_MULTIPLE);
165 $form_state->setValue('tid', $term->id());
166 $form_state->set('tid', $term->id());