class TermForm

Same name in other branches
  1. 9 core/modules/taxonomy/src/TermForm.php \Drupal\taxonomy\TermForm
  2. 8.9.x core/modules/taxonomy/src/TermForm.php \Drupal\taxonomy\TermForm
  3. 10 core/modules/taxonomy/src/TermForm.php \Drupal\taxonomy\TermForm

Base for handler for taxonomy term edit forms.

@internal

Hierarchy

Expanded class hierarchy of TermForm

2 files declare their use of TermForm
ForumForm.php in core/modules/forum/src/Form/ForumForm.php
Term.php in core/modules/taxonomy/src/Entity/Term.php

File

core/modules/taxonomy/src/TermForm.php, line 14

Namespace

Drupal\taxonomy
View source
class TermForm extends ContentEntityForm {
    
    /**
     * {@inheritdoc}
     */
    public function form(array $form, FormStateInterface $form_state) {
        $term = $this->entity;
        $vocab_storage = $this->entityTypeManager
            ->getStorage('taxonomy_vocabulary');
        
        /** @var \Drupal\taxonomy\TermStorageInterface $taxonomy_storage */
        $taxonomy_storage = $this->entityTypeManager
            ->getStorage('taxonomy_term');
        $vocabulary = $vocab_storage->load($term->bundle());
        $parent = $this->getParentIds($term);
        $form_state->set([
            'taxonomy',
            'parent',
        ], $parent);
        $form_state->set([
            'taxonomy',
            'vocabulary',
        ], $vocabulary);
        $form['relations'] = [
            '#type' => 'details',
            '#title' => $this->t('Relations'),
            '#open' => $taxonomy_storage->getVocabularyHierarchyType($vocabulary->id()) == VocabularyInterface::HIERARCHY_MULTIPLE,
            '#weight' => 10,
        ];
        // \Drupal\taxonomy\TermStorageInterface::loadTree() and
        // \Drupal\taxonomy\TermStorageInterface::loadParents() may contain large
        // numbers of items so we check for taxonomy.settings:override_selector
        // before loading the full vocabulary. Contrib modules can then intercept
        // before hook_form_alter to provide scalable alternatives.
        if (!$this->config('taxonomy.settings')
            ->get('override_selector')) {
            $exclude = [];
            if (!$term->isNew()) {
                $children = $taxonomy_storage->loadTree($vocabulary->id(), $term->id());
                // A term can't be the child of itself, nor of its children.
                foreach ($children as $child) {
                    $exclude[] = $child->tid;
                }
                $exclude[] = $term->id();
            }
            $tree = $taxonomy_storage->loadTree($vocabulary->id());
            $options = [
                '<' . $this->t('root') . '>',
            ];
            if (empty($parent)) {
                $parent = [
                    0,
                ];
            }
            foreach ($tree as $item) {
                if (!in_array($item->tid, $exclude)) {
                    $options[$item->tid] = str_repeat('-', $item->depth) . $item->name;
                }
            }
        }
        else {
            $options = [
                '<' . $this->t('root') . '>',
            ];
            $parent = [
                0,
            ];
        }
        if ($this->getRequest()->query
            ->has('parent')) {
            $parent = array_values(array_intersect(array_keys($options), (array) $this->getRequest()->query
                ->all()['parent']));
        }
        $form['relations']['parent'] = [
            '#type' => 'select',
            '#title' => $this->t('Parent terms'),
            '#options' => $options,
            '#default_value' => $parent,
            '#multiple' => TRUE,
        ];
        $form['relations']['weight'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Weight'),
            '#size' => 6,
            '#default_value' => $term->getWeight(),
            '#description' => $this->t('Terms are displayed in ascending order by weight.'),
            '#required' => TRUE,
        ];
        $form['vid'] = [
            '#type' => 'value',
            '#value' => $vocabulary->id(),
        ];
        $form['tid'] = [
            '#type' => 'value',
            '#value' => $term->id(),
        ];
        return parent::form($form, $form_state);
    }
    
    /**
     * {@inheritdoc}
     */
    protected function actions(array $form, FormStateInterface $form_state) {
        $element = parent::actions($form, $form_state);
        if (!$this->getRequest()->query
            ->has('destination')) {
            $element['overview'] = [
                '#type' => 'submit',
                '#value' => $this->t('Save and go to list'),
                '#weight' => 20,
                '#submit' => array_merge($element['submit']['#submit'], [
                    '::overview',
                ]),
                '#access' => $this->currentUser()
                    ->hasPermission('access taxonomy overview'),
            ];
        }
        return $element;
    }
    
    /**
     * Form submission handler for the 'overview' action.
     *
     * @param array[] $form
     *   An associative array containing the structure of the form.
     * @param \Drupal\Core\Form\FormStateInterface $form_state
     *   The current state of the form.
     */
    public function overview(array $form, FormStateInterface $form_state) : void {
        $vocabulary = $this->entityTypeManager
            ->getStorage('taxonomy_vocabulary')
            ->load($form_state->getValue('vid'));
        $form_state->setRedirectUrl($vocabulary->toUrl('overview-form'));
    }
    
    /**
     * {@inheritdoc}
     */
    public function validateForm(array &$form, FormStateInterface $form_state) {
        parent::validateForm($form, $form_state);
        // Ensure numeric values.
        if ($form_state->hasValue('weight') && !is_numeric($form_state->getValue('weight'))) {
            $form_state->setErrorByName('weight', $this->t('Weight value must be numeric.'));
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function buildEntity(array $form, FormStateInterface $form_state) {
        $term = parent::buildEntity($form, $form_state);
        // Prevent leading and trailing spaces in term names.
        $term->setName(trim($term->getName()));
        // Assign parents with proper delta values starting from 0.
        $term->parent = array_values($form_state->getValue('parent'));
        return $term;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function getEditedFieldNames(FormStateInterface $form_state) {
        return array_merge([
            'parent',
            'weight',
        ], parent::getEditedFieldNames($form_state));
    }
    
    /**
     * {@inheritdoc}
     */
    protected function flagViolations(EntityConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) {
        // Manually flag violations of fields not handled by the form display. This
        // is necessary as entity form displays only flag violations for fields
        // contained in the display.
        // @see ::form()
        foreach ($violations->getByField('parent') as $violation) {
            $form_state->setErrorByName('parent', $violation->getMessage());
        }
        foreach ($violations->getByField('weight') as $violation) {
            $form_state->setErrorByName('weight', $violation->getMessage());
        }
        parent::flagViolations($violations, $form, $form_state);
    }
    
    /**
     * {@inheritdoc}
     */
    public function save(array $form, FormStateInterface $form_state) {
        $term = $this->entity;
        $result = $term->save();
        $edit_link = $term->toLink($this->t('Edit'), 'edit-form')
            ->toString();
        $view_link = $term->toLink()
            ->toString();
        switch ($result) {
            case SAVED_NEW:
                $this->messenger()
                    ->addStatus($this->t('Created new term %term.', [
                    '%term' => $view_link,
                ]));
                $this->logger('taxonomy')
                    ->info('Created new term %term.', [
                    '%term' => $term->getName(),
                    'link' => $edit_link,
                ]);
                break;
            case SAVED_UPDATED:
                $this->messenger()
                    ->addStatus($this->t('Updated term %term.', [
                    '%term' => $view_link,
                ]));
                $this->logger('taxonomy')
                    ->info('Updated term %term.', [
                    '%term' => $term->getName(),
                    'link' => $edit_link,
                ]);
                // Redirect to term view page if user has access, otherwise the form
                // will be displayed again.
                $canonicalUrl = $term->toUrl();
                if ($canonicalUrl->access()) {
                    $form_state->setRedirectUrl($canonicalUrl);
                }
                break;
        }
        $current_parent_count = count($form_state->getValue('parent'));
        // Root doesn't count if it's the only parent.
        if ($current_parent_count == 1 && $form_state->hasValue([
            'parent',
            0,
        ])) {
            $form_state->setValue('parent', []);
        }
        $form_state->setValue('tid', $term->id());
        $form_state->set('tid', $term->id());
    }
    
    /**
     * Returns term parent IDs, including the root.
     *
     * @param \Drupal\taxonomy\TermInterface $term
     *   The taxonomy term entity.
     *
     * @return array
     *   A list if parent term IDs.
     */
    protected function getParentIds(TermInterface $term) : array {
        $parent = [];
        // Get the parent directly from the term as
        // \Drupal\taxonomy\TermStorageInterface::loadParents() excludes the root.
        foreach ($term->get('parent') as $item) {
            $parent[] = (int) $item->target_id;
        }
        return $parent;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
ContentEntityForm::$entity protected property The entity being used by this form. Overrides EntityForm::$entity 9
ContentEntityForm::$entityRepository protected property The entity repository service.
ContentEntityForm::$entityTypeBundleInfo protected property The entity type bundle info service.
ContentEntityForm::$time protected property The time service.
ContentEntityForm::addRevisionableFormFields protected function Add revision form fields if the entity enabled the UI.
ContentEntityForm::copyFormValuesToEntity protected function Overrides EntityForm::copyFormValuesToEntity
ContentEntityForm::create public static function Overrides FormBase::create 9
ContentEntityForm::getBundleEntity protected function Returns the bundle entity of the entity, or NULL if there is none.
ContentEntityForm::getFormDisplay public function Overrides ContentEntityFormInterface::getFormDisplay
ContentEntityForm::getFormLangcode public function Overrides ContentEntityFormInterface::getFormLangcode
ContentEntityForm::getNewRevisionDefault protected function Should new revisions created on default.
ContentEntityForm::init protected function Initializes the form state and the entity before the first form build. Overrides EntityForm::init 1
ContentEntityForm::initFormLangcodes protected function Initializes form language code values.
ContentEntityForm::isDefaultFormLangcode public function Overrides ContentEntityFormInterface::isDefaultFormLangcode
ContentEntityForm::prepareEntity protected function Overrides EntityForm::prepareEntity 1
ContentEntityForm::setFormDisplay public function Overrides ContentEntityFormInterface::setFormDisplay
ContentEntityForm::showRevisionUi protected function Checks whether the revision form fields should be added to the form.
ContentEntityForm::submitForm public function Overrides EntityForm::submitForm 3
ContentEntityForm::updateChangedTime public function Updates the changed time of the entity.
ContentEntityForm::updateFormLangcode public function Updates the form language to reflect any change to the entity language.
ContentEntityForm::__construct public function Constructs a ContentEntityForm object. 8
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
EntityForm::$entityTypeManager protected property The entity type manager. 3
EntityForm::$moduleHandler protected property The module handler service. 2
EntityForm::$operation protected property The name of the current operation.
EntityForm::actionsElement protected function Returns the action form element for the current entity form.
EntityForm::afterBuild public function Form element #after_build callback: Updates the entity with submitted data. 1
EntityForm::buildForm public function Overrides FormInterface::buildForm 13
EntityForm::getBaseFormId public function Overrides BaseFormIdInterface::getBaseFormId 4
EntityForm::getEntity public function Overrides EntityFormInterface::getEntity
EntityForm::getEntityFromRouteMatch public function Overrides EntityFormInterface::getEntityFromRouteMatch 3
EntityForm::getFormId public function Overrides FormInterface::getFormId 13
EntityForm::getOperation public function Overrides EntityFormInterface::getOperation
EntityForm::prepareInvokeAll protected function Invokes the specified prepare hook variant.
EntityForm::processForm public function Process callback: assigns weights and hides extra fields.
EntityForm::setEntity public function Overrides EntityFormInterface::setEntity
EntityForm::setEntityTypeManager public function Overrides EntityFormInterface::setEntityTypeManager
EntityForm::setModuleHandler public function Overrides EntityFormInterface::setModuleHandler
EntityForm::setOperation public function Overrides EntityFormInterface::setOperation
FormBase::$configFactory protected property The config factory. 2
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 2
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user. 2
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route.
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 16
MessengerTrait::messenger public function Gets the messenger. 16
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 2
RedirectDestinationTrait::getDestinationArray protected function Prepares a &#039;destination&#039; URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TermForm::actions protected function Overrides EntityForm::actions 1
TermForm::buildEntity public function Overrides ContentEntityForm::buildEntity 1
TermForm::flagViolations protected function Overrides ContentEntityForm::flagViolations
TermForm::form public function Overrides ContentEntityForm::form 1
TermForm::getEditedFieldNames protected function Overrides ContentEntityForm::getEditedFieldNames
TermForm::getParentIds protected function Returns term parent IDs, including the root.
TermForm::overview public function Form submission handler for the &#039;overview&#039; action.
TermForm::save public function Overrides EntityForm::save 1
TermForm::validateForm public function Overrides ContentEntityForm::validateForm

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.