Pull merge.
[yaffs-website] / web / core / modules / taxonomy / src / TermForm.php
1 <?php
2
3 namespace Drupal\taxonomy;
4
5 use Drupal\Core\Entity\ContentEntityForm;
6 use Drupal\Core\Form\FormStateInterface;
7
8 /**
9  * Base for handler for taxonomy term edit forms.
10  *
11  * @internal
12  */
13 class TermForm extends ContentEntityForm {
14
15   /**
16    * {@inheritdoc}
17    */
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());
23
24     $parent = array_keys($taxonomy_storage->loadParents($term->id()));
25     $form_state->set(['taxonomy', 'parent'], $parent);
26     $form_state->set(['taxonomy', 'vocabulary'], $vocabulary);
27
28     $form['relations'] = [
29       '#type' => 'details',
30       '#title' => $this->t('Relations'),
31       '#open' => $vocabulary->getHierarchy() == VocabularyInterface::HIERARCHY_MULTIPLE,
32       '#weight' => 10,
33     ];
34
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')) {
41       $exclude = [];
42       if (!$term->isNew()) {
43         $parent = array_keys($taxonomy_storage->loadParents($term->id()));
44         $children = $taxonomy_storage->loadTree($vocabulary->id(), $term->id());
45
46         // A term can't be the child of itself, nor of its children.
47         foreach ($children as $child) {
48           $exclude[] = $child->tid;
49         }
50         $exclude[] = $term->id();
51       }
52
53       $tree = $taxonomy_storage->loadTree($vocabulary->id());
54       $options = ['<' . $this->t('root') . '>'];
55       if (empty($parent)) {
56         $parent = [0];
57       }
58
59       foreach ($tree as $item) {
60         if (!in_array($item->tid, $exclude)) {
61           $options[$item->tid] = str_repeat('-', $item->depth) . $item->name;
62         }
63       }
64
65       $form['relations']['parent'] = [
66         '#type' => 'select',
67         '#title' => $this->t('Parent terms'),
68         '#options' => $options,
69         '#default_value' => $parent,
70         '#multiple' => TRUE,
71       ];
72     }
73
74     $form['relations']['weight'] = [
75       '#type' => 'textfield',
76       '#title' => $this->t('Weight'),
77       '#size' => 6,
78       '#default_value' => $term->getWeight(),
79       '#description' => $this->t('Terms are displayed in ascending order by weight.'),
80       '#required' => TRUE,
81     ];
82
83     $form['vid'] = [
84       '#type' => 'value',
85       '#value' => $vocabulary->id(),
86     ];
87
88     $form['tid'] = [
89       '#type' => 'value',
90       '#value' => $term->id(),
91     ];
92
93     return parent::form($form, $form_state);
94   }
95
96   /**
97    * {@inheritdoc}
98    */
99   public function validateForm(array &$form, FormStateInterface $form_state) {
100     parent::validateForm($form, $form_state);
101
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.'));
105     }
106   }
107
108   /**
109    * {@inheritdoc}
110    */
111   public function buildEntity(array $form, FormStateInterface $form_state) {
112     $term = parent::buildEntity($form, $form_state);
113
114     // Prevent leading and trailing spaces in term names.
115     $term->setName(trim($term->getName()));
116
117     // Assign parents with proper delta values starting from 0.
118     $term->parent = array_keys($form_state->getValue('parent'));
119
120     return $term;
121   }
122
123   /**
124    * {@inheritdoc}
125    */
126   public function save(array $form, FormStateInterface $form_state) {
127     $term = $this->entity;
128
129     $result = $term->save();
130
131     $edit_link = $term->link($this->t('Edit'), 'edit-form');
132     $view_link = $term->link($term->getName());
133     switch ($result) {
134       case SAVED_NEW:
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]);
137         break;
138       case SAVED_UPDATED:
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]);
141         break;
142     }
143
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', []);
150     }
151
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());
157     }
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);
162       $vocabulary->save();
163     }
164
165     $form_state->setValue('tid', $term->id());
166     $form_state->set('tid', $term->id());
167   }
168
169 }