Chris@0: entity; Chris@18: $vocab_storage = $this->entityTypeManager->getStorage('taxonomy_vocabulary'); Chris@18: /** @var \Drupal\taxonomy\TermStorageInterface $taxonomy_storage */ Chris@18: $taxonomy_storage = $this->entityTypeManager->getStorage('taxonomy_term'); Chris@0: $vocabulary = $vocab_storage->load($term->bundle()); Chris@0: Chris@0: $parent = array_keys($taxonomy_storage->loadParents($term->id())); Chris@0: $form_state->set(['taxonomy', 'parent'], $parent); Chris@0: $form_state->set(['taxonomy', 'vocabulary'], $vocabulary); Chris@0: Chris@0: $form['relations'] = [ Chris@0: '#type' => 'details', Chris@0: '#title' => $this->t('Relations'), Chris@18: '#open' => $taxonomy_storage->getVocabularyHierarchyType($vocabulary->id()) == VocabularyInterface::HIERARCHY_MULTIPLE, Chris@0: '#weight' => 10, Chris@0: ]; Chris@0: Chris@0: // \Drupal\taxonomy\TermStorageInterface::loadTree() and Chris@0: // \Drupal\taxonomy\TermStorageInterface::loadParents() may contain large Chris@0: // numbers of items so we check for taxonomy.settings:override_selector Chris@0: // before loading the full vocabulary. Contrib modules can then intercept Chris@0: // before hook_form_alter to provide scalable alternatives. Chris@0: if (!$this->config('taxonomy.settings')->get('override_selector')) { Chris@14: $exclude = []; Chris@14: if (!$term->isNew()) { Chris@14: $parent = array_keys($taxonomy_storage->loadParents($term->id())); Chris@14: $children = $taxonomy_storage->loadTree($vocabulary->id(), $term->id()); Chris@0: Chris@14: // A term can't be the child of itself, nor of its children. Chris@14: foreach ($children as $child) { Chris@14: $exclude[] = $child->tid; Chris@14: } Chris@14: $exclude[] = $term->id(); Chris@0: } Chris@0: Chris@0: $tree = $taxonomy_storage->loadTree($vocabulary->id()); Chris@0: $options = ['<' . $this->t('root') . '>']; Chris@0: if (empty($parent)) { Chris@0: $parent = [0]; Chris@0: } Chris@0: Chris@0: foreach ($tree as $item) { Chris@0: if (!in_array($item->tid, $exclude)) { Chris@0: $options[$item->tid] = str_repeat('-', $item->depth) . $item->name; Chris@0: } Chris@0: } Chris@0: Chris@0: $form['relations']['parent'] = [ Chris@0: '#type' => 'select', Chris@0: '#title' => $this->t('Parent terms'), Chris@0: '#options' => $options, Chris@0: '#default_value' => $parent, Chris@0: '#multiple' => TRUE, Chris@0: ]; Chris@0: } Chris@0: Chris@0: $form['relations']['weight'] = [ Chris@0: '#type' => 'textfield', Chris@0: '#title' => $this->t('Weight'), Chris@0: '#size' => 6, Chris@0: '#default_value' => $term->getWeight(), Chris@0: '#description' => $this->t('Terms are displayed in ascending order by weight.'), Chris@0: '#required' => TRUE, Chris@0: ]; Chris@0: Chris@0: $form['vid'] = [ Chris@0: '#type' => 'value', Chris@0: '#value' => $vocabulary->id(), Chris@0: ]; Chris@0: Chris@0: $form['tid'] = [ Chris@0: '#type' => 'value', Chris@0: '#value' => $term->id(), Chris@0: ]; Chris@0: Chris@0: return parent::form($form, $form_state); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function validateForm(array &$form, FormStateInterface $form_state) { Chris@0: parent::validateForm($form, $form_state); Chris@0: Chris@0: // Ensure numeric values. Chris@0: if ($form_state->hasValue('weight') && !is_numeric($form_state->getValue('weight'))) { Chris@0: $form_state->setErrorByName('weight', $this->t('Weight value must be numeric.')); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function buildEntity(array $form, FormStateInterface $form_state) { Chris@0: $term = parent::buildEntity($form, $form_state); Chris@0: Chris@0: // Prevent leading and trailing spaces in term names. Chris@0: $term->setName(trim($term->getName())); Chris@0: Chris@0: // Assign parents with proper delta values starting from 0. Chris@0: $term->parent = array_keys($form_state->getValue('parent')); Chris@0: Chris@0: return $term; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@18: protected function getEditedFieldNames(FormStateInterface $form_state) { Chris@18: return array_merge(['parent', 'weight'], parent::getEditedFieldNames($form_state)); Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: protected function flagViolations(EntityConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) { Chris@18: // Manually flag violations of fields not handled by the form display. This Chris@18: // is necessary as entity form displays only flag violations for fields Chris@18: // contained in the display. Chris@18: // @see ::form() Chris@18: foreach ($violations->getByField('parent') as $violation) { Chris@18: $form_state->setErrorByName('parent', $violation->getMessage()); Chris@18: } Chris@18: foreach ($violations->getByField('weight') as $violation) { Chris@18: $form_state->setErrorByName('weight', $violation->getMessage()); Chris@18: } Chris@18: Chris@18: parent::flagViolations($violations, $form, $form_state); Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@0: public function save(array $form, FormStateInterface $form_state) { Chris@0: $term = $this->entity; Chris@0: Chris@0: $result = $term->save(); Chris@0: Chris@18: $edit_link = $term->toLink($this->t('Edit'), 'edit-form')->toString(); Chris@18: $view_link = $term->toLink()->toString(); Chris@0: switch ($result) { Chris@0: case SAVED_NEW: Chris@17: $this->messenger()->addStatus($this->t('Created new term %term.', ['%term' => $view_link])); Chris@0: $this->logger('taxonomy')->notice('Created new term %term.', ['%term' => $term->getName(), 'link' => $edit_link]); Chris@0: break; Chris@0: case SAVED_UPDATED: Chris@17: $this->messenger()->addStatus($this->t('Updated term %term.', ['%term' => $view_link])); Chris@0: $this->logger('taxonomy')->notice('Updated term %term.', ['%term' => $term->getName(), 'link' => $edit_link]); Chris@0: break; Chris@0: } Chris@0: Chris@0: $current_parent_count = count($form_state->getValue('parent')); Chris@0: // Root doesn't count if it's the only parent. Chris@0: if ($current_parent_count == 1 && $form_state->hasValue(['parent', 0])) { Chris@0: $form_state->setValue('parent', []); Chris@0: } Chris@0: Chris@0: $form_state->setValue('tid', $term->id()); Chris@0: $form_state->set('tid', $term->id()); Chris@0: } Chris@0: Chris@0: }