diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 2cf0c53..d7e731d 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -668,7 +668,7 @@ function forum_system_info_alter(&$info, Extension $file, $type) { if ($vocabulary->access('view')) { $info['explanation'] = t('To uninstall Forum first delete all Forum content and %vocabulary terms.', [ '%vocabulary' => $vocabulary->label(), - '!url' => $vocabulary->url('overview-form'), + '!url' => $vocabulary->url('edit-form'), ]); } else { @@ -680,7 +680,7 @@ function forum_system_info_alter(&$info, Extension $file, $type) { else { $info['explanation'] = t('To uninstall Forum first delete all %vocabulary terms.', [ '%vocabulary' => $vocabulary->label(), - '!url' => $vocabulary->url('overview-form'), + '!url' => $vocabulary->url('edit-form'), ]); } } diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php index 7ca9dd7..df9380a 100644 --- a/core/modules/taxonomy/src/Entity/Term.php +++ b/core/modules/taxonomy/src/Entity/Term.php @@ -44,7 +44,7 @@ * "uuid" = "uuid" * }, * bundle_entity_type = "taxonomy_vocabulary", - * field_ui_base_route = "entity.taxonomy_vocabulary.overview_form", + * field_ui_base_route = "entity.taxonomy_vocabulary.edit_form", * common_reference_target = TRUE, * links = { * "canonical" = "/taxonomy/term/{taxonomy_term}", diff --git a/core/modules/taxonomy/src/VocabularyForm.php b/core/modules/taxonomy/src/Form/OverviewTerms.php similarity index 64% copy from core/modules/taxonomy/src/VocabularyForm.php copy to core/modules/taxonomy/src/Form/OverviewTerms.php index 905f53a..bea43e7 100644 --- a/core/modules/taxonomy/src/VocabularyForm.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -2,50 +2,50 @@ /** * @file - * Contains \Drupal\taxonomy\VocabularyForm. + * Contains \Drupal\taxonomy\Form\OverviewTerms */ -namespace Drupal\taxonomy; +namespace Drupal\taxonomy\Form; -use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Form\FormBase; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Language\LanguageInterface; -use Drupal\language\Entity\ContentLanguageSettings; +use Drupal\taxonomy\VocabularyInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -/** - * Base form for vocabulary edit forms. +/* + * Provides terms overview form for a taxonomy vocabulary. + * + * @todo Decouple \Drupal\forum\Form\Overview and remove this. */ -class VocabularyForm extends EntityForm { +class OverviewTerms extends FormBase { /** - * The term storage controller. + * The module handler service. * - * @var \Drupal\taxonomy\TermStorageInterface + * @var \Drupal\Core\Extension\ModuleHandlerInterface */ - protected $termStorage; + protected $moduleHandler; /** - * The vocabulary storage. + * The term storage controller. * - * @var \Drupal\taxonomy\VocabularyStorageInterface. + * @var \Drupal\taxonomy\TermStorageInterface */ - protected $vocabularyStorage; + protected $storageController; /** - * Constructs a new vocabulary form. + * Constructs an OverviewTerms object. * * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler service. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager service. */ - public function __construct(EntityManagerInterface $entity_manager) { - $this->termStorage = $entity_manager->getStorage('taxonomy_term'); - $this->vocabularyStorage = $entity_manager->getStorage('taxonomy_vocabulary'); + public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) { + $this->moduleHandler = $module_handler; + $this->storageController = $entity_manager->getStorage('taxonomy_term'); } /** @@ -53,6 +53,7 @@ public function __construct(EntityManagerInterface $entity_manager) { */ public static function create(ContainerInterface $container) { return new static( + $container->get('module_handler'), $container->get('entity.manager') ); } @@ -60,86 +61,12 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} */ - public function form(array $form, FormStateInterface $form_state) { - $vocabulary = $this->entity; - if ($vocabulary->isNew()) { - $form['#title'] = $this->t('Add vocabulary'); - } - else { - $form['#title'] = $this->t('Edit vocabulary'); - } - - $form['name'] = array( - '#type' => 'textfield', - '#title' => $this->t('Name'), - '#default_value' => $vocabulary->label(), - '#maxlength' => 255, - '#required' => TRUE, - ); - $form['vid'] = array( - '#type' => 'machine_name', - '#default_value' => $vocabulary->id(), - '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH, - '#machine_name' => array( - 'exists' => array($this, 'exists'), - 'source' => array('name'), - ), - ); - $form['description'] = array( - '#type' => 'textfield', - '#title' => $this->t('Description'), - '#default_value' => $vocabulary->getDescription(), - ); - - // $form['langcode'] is not wrapped in an - // if ($this->moduleHandler->moduleExists('language')) check because the - // language_select form element works also without the language module being - // installed. http://drupal.org/node/1749954 documents the new element. - $form['langcode'] = array( - '#type' => 'language_select', - '#title' => $this->t('Vocabulary language'), - '#languages' => LanguageInterface::STATE_ALL, - '#default_value' => $vocabulary->language()->getId(), - ); - if ($this->moduleHandler->moduleExists('language')) { - $form['default_terms_language'] = array( - '#type' => 'details', - '#title' => $this->t('Terms language'), - '#open' => TRUE, - ); - $form['default_terms_language']['default_language'] = array( - '#type' => 'language_configuration', - '#entity_information' => array( - 'entity_type' => 'taxonomy_term', - 'bundle' => $vocabulary->id(), - ), - '#default_value' => ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vocabulary->id()), - ); - } - // Set the hierarchy to "multiple parents" by default. This simplifies the - // vocabulary form and standardizes the term form. - $form['hierarchy'] = array( - '#type' => 'value', - '#value' => '0', - ); - - // Add terms overview form for an existing taxonomy vocabulary. - if (!$vocabulary->isNew()) { - // Form API supports constructing and validating self-contained sections - // within forms, but does not allow handling the form section's submission - // equally separated yet. Therefore, we use a $form_state key to point to - // the parents of the form section. - // @see self::submitOverviewForm() - $form_state->set('taxonomy_overview_terms', ['taxonomy_terms']); - $form['terms'] = array(); - $form['terms'] = $this->buildOverviewForm($form['terms'], $form_state, $vocabulary); - } - - return parent::form($form, $form_state, $vocabulary); + public function getFormId() { + return 'taxonomy_overview_terms'; } /** - * Form constructor fro over view form. + * Form constructor. * * Display a tree of all the terms in a vocabulary, with options to edit * each one. The form is made drag and drop by the theme function. @@ -154,26 +81,10 @@ public function form(array $form, FormStateInterface $form_state) { * @return array * The form structure. */ - protected function buildOverviewForm($form, $form_state, VocabularyInterface $taxonomy_vocabulary) { + public function buildForm(array $form, FormStateInterface $form_state, VocabularyInterface $taxonomy_vocabulary = NULL) { // @todo Remove global variables when http://drupal.org/node/2044435 is in. global $pager_page_array, $pager_total, $pager_total_items; - // Ensure that self::submitOverviewForm() knows the parents of this form - // section. - if (!$form_state->has('taxonomy_overview_terms')) { - $form_state->set('taxonomy_overview_terms', []); - } - else { - // Form API supports constructing and validating self-contained sections - // within forms, but does not allow to handle the form section's - // submission equally separated yet. Therefore, we use a $form_state key - // to point to the parents of the form section. - $parents = $form_state->get('taxonomy_overview_terms'); - // If this form was already submitted once, it's probably hit a validation - // error. Ensure the form is rebuilt in the same order as the user - // submitted. - $user_input = NestedArray::getValue($form_state->getUserInput(), $parents); - } $form_state->set(['taxonomy', 'vocabulary'], $taxonomy_vocabulary); $parent_fields = FALSE; @@ -200,7 +111,7 @@ protected function buildOverviewForm($form, $form_state, VocabularyInterface $ta $delta = 0; $term_deltas = array(); - $tree = $this->termStorage->loadTree($taxonomy_vocabulary->id(), 0, NULL, TRUE); + $tree = $this->storageController->loadTree($taxonomy_vocabulary->id(), 0, NULL, TRUE); $tree_index = 0; do { // In case this tree is completely empty. @@ -269,6 +180,10 @@ protected function buildOverviewForm($form, $form_state, VocabularyInterface $ta $pager_page_array[0] = $page; $pager_total[0] = ceil($total_entries / $page_increment); + // If this form was already submitted once, it's probably hit a validation + // error. Ensure the form is rebuilt in the same order as the user + // submitted. + $user_input = $form_state->getUserInput(); if (!empty($user_input)) { // Get the POST order. $order = array_flip(array_keys($user_input['terms'])); @@ -431,70 +346,25 @@ protected function buildOverviewForm($form, $form_state, VocabularyInterface $ta 'group' => 'term-weight', ); - return $form; - } - - /** - * {@inheritdoc} - */ - protected function actions(array $form, FormStateInterface $form_state) { - // If we are displaying the delete confirmation skip the regular actions. - if (!$form_state->get('confirm_delete')) { - $actions = parent::actions($form, $form_state); - if (!$this->entity->isNew() && $this->entity->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE) { - $actions['reset_alphabetical'] = array( - '#type' => 'submit', - '#submit' => array('::submitReset'), - '#value' => $this->t('Reset to alphabetical'), - ); - } - // We cannot leverage the regular submit handler definition because we - // have button-specific ones here. Hence we need to explicitly set it for - // the submit action, otherwise it would be ignored. - if ($this->moduleHandler->moduleExists('content_translation')) { - array_unshift($actions['submit']['#submit'], 'content_translation_language_configuration_element_submit'); - } - return $actions; - } - else { - return array(); - } - } - - /** - * {@inheritdoc} - */ - public function save(array $form, FormStateInterface $form_state) { - $vocabulary = $this->entity; - if (!$vocabulary->isNew()) { - $this->submitOverviewForm($form, $form_state, $vocabulary); - } - - // Prevent leading and trailing spaces in vocabulary names. - $vocabulary->set('name', trim($vocabulary->label())); - - $status = $vocabulary->save(); - $edit_link = $this->entity->link($this->t('Edit')); - switch ($status) { - case SAVED_NEW: - drupal_set_message($this->t('Created new vocabulary %name.', array('%name' => $vocabulary->label()))); - $this->logger('taxonomy')->notice('Created new vocabulary %name.', array('%name' => $vocabulary->label(), 'link' => $edit_link)); - $form_state->setRedirectUrl($vocabulary->urlInfo('overview-form')); - break; - - case SAVED_UPDATED: - drupal_set_message($this->t('Updated the configuration of vocabulary %name.', array('%name' => $vocabulary->label()))); - $this->logger('taxonomy')->notice('Updated the configuration of vocabulary %name.', array('%name' => $vocabulary->label(), 'link' => $edit_link)); - $form_state->setRedirectUrl($vocabulary->urlInfo('collection')); - break; + if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) { + $form['actions'] = array('#type' => 'actions', '#tree' => FALSE); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => $this->t('Save'), + '#button_type' => 'primary', + ); + $form['actions']['reset_alphabetical'] = array( + '#type' => 'submit', + '#submit' => array('::submitReset'), + '#value' => $this->t('Reset to alphabetical'), + ); } - $form_state->setValue('vid', $vocabulary->id()); - $form_state->set('vid', $vocabulary->id()); + return $form; } /** - * Form submission handler for overview form. + * Form submission handler. * * Rather than using a textfield or weight field, this form depends entirely * upon the order of form elements on the page to determine new weights. @@ -506,31 +376,23 @@ public function save(array $form, FormStateInterface $form_state) { * skipped when a term has children so that reordering is minimal when a child * is added or removed from a term. * - * @param array $complete_form + * @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. - * @param \Drupal\taxonomy\VocabularyInterface $vocabulary - * The vocabulary to display the overview form for. */ - protected function submitOverviewForm(array $complete_form, FormStateInterface $form_state, VocabularyInterface $vocabulary) { - // Form API supports constructing and validating self-contained sections - // within forms, but does not allow to handle the form section's submission - // equally separated yet. Therefore, we use a $form_state key to point to - // the parents of the form section. - $parents = $form_state->get('taxonomy_overview_terms'); - $form = &NestedArray::getValue($complete_form, $parents); - + public function submitForm(array &$form, FormStateInterface $form_state) { // Sort term order based on weight. uasort($form_state->getValue('terms'), array('Drupal\Component\Utility\SortArray', 'sortByWeightElement')); + $vocabulary = $form_state->get(['taxonomy', 'vocabulary']); // Update the current hierarchy type as we go. $hierarchy = TAXONOMY_HIERARCHY_DISABLED; $changed_terms = array(); // @todo taxonomy_get_tree needs to be converted to a service and injected. // Will be fixed in http://drupal.org/node/1976298. - $tree = $this->termStorage->loadTree($vocabulary->id(), 0, NULL, TRUE); + $tree = taxonomy_get_tree($vocabulary->id(), 0, NULL, TRUE); if (empty($tree)) { return; @@ -598,6 +460,7 @@ protected function submitOverviewForm(array $complete_form, FormStateInterface $ $vocabulary->setHierarchy($hierarchy); $vocabulary->save(); } + drupal_set_message($this->t('The configuration options have been saved.')); } /** @@ -609,18 +472,5 @@ public function submitReset(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($vocabulary->urlInfo('reset-form')); } - /** - * Determines if the vocabulary already exists. - * - * @param string $id - * The vocabulary ID - * - * @return bool - * TRUE if the vocabulary exists, FALSE otherwise. - */ - public function exists($id) { - $action = $this->vocabularyStorage->load($id); - return !empty($action); - } - } + diff --git a/core/modules/taxonomy/src/Form/VocabularyResetForm.php b/core/modules/taxonomy/src/Form/VocabularyResetForm.php index 4b8ed85..069d09f 100644 --- a/core/modules/taxonomy/src/Form/VocabularyResetForm.php +++ b/core/modules/taxonomy/src/Form/VocabularyResetForm.php @@ -61,7 +61,7 @@ public function getQuestion() { * {@inheritdoc} */ public function getCancelUrl() { - return $this->entity->urlInfo('overview-form'); + return $this->entity->urlInfo('edit-form'); } /** diff --git a/core/modules/taxonomy/src/Tests/VocabularyUiTest.php b/core/modules/taxonomy/src/Tests/VocabularyUiTest.php index aa24cee..a2c2ece 100644 --- a/core/modules/taxonomy/src/Tests/VocabularyUiTest.php +++ b/core/modules/taxonomy/src/Tests/VocabularyUiTest.php @@ -8,6 +8,7 @@ namespace Drupal\taxonomy\Tests; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Url; use Drupal\taxonomy\Entity\Vocabulary; /** @@ -50,6 +51,7 @@ function testVocabularyInterface() { // Edit the vocabulary. $this->drupalGet('admin/structure/taxonomy'); $this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.'); + $this->assertLinkByHref(Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $edit['vid']])); $this->clickLink(t('Edit vocabulary')); $edit = array(); $edit['name'] = $this->randomMachineName(); diff --git a/core/modules/taxonomy/src/VocabularyForm.php b/core/modules/taxonomy/src/VocabularyForm.php index 905f53a..7db1d9c 100644 --- a/core/modules/taxonomy/src/VocabularyForm.php +++ b/core/modules/taxonomy/src/VocabularyForm.php @@ -441,7 +441,8 @@ protected function actions(array $form, FormStateInterface $form_state) { // If we are displaying the delete confirmation skip the regular actions. if (!$form_state->get('confirm_delete')) { $actions = parent::actions($form, $form_state); - if (!$this->entity->isNew() && $this->entity->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE) { + $tree = $this->termStorage->loadTree($this->entity->id(), 0, NULL, TRUE); + if (!$this->entity->isNew() && $this->entity->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) { $actions['reset_alphabetical'] = array( '#type' => 'submit', '#submit' => array('::submitReset'), @@ -479,7 +480,7 @@ public function save(array $form, FormStateInterface $form_state) { case SAVED_NEW: drupal_set_message($this->t('Created new vocabulary %name.', array('%name' => $vocabulary->label()))); $this->logger('taxonomy')->notice('Created new vocabulary %name.', array('%name' => $vocabulary->label(), 'link' => $edit_link)); - $form_state->setRedirectUrl($vocabulary->urlInfo('overview-form')); + $form_state->setRedirectUrl($vocabulary->urlInfo('edit-form')); break; case SAVED_UPDATED: diff --git a/core/modules/taxonomy/src/VocabularyListBuilder.php b/core/modules/taxonomy/src/VocabularyListBuilder.php index 5b0d768..af762ee 100644 --- a/core/modules/taxonomy/src/VocabularyListBuilder.php +++ b/core/modules/taxonomy/src/VocabularyListBuilder.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Entity\DraggableListBuilder; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Url; /** * Defines a class to build a listing of taxonomy vocabulary entities. @@ -38,12 +39,13 @@ public function getDefaultOperations(EntityInterface $entity) { if (isset($operations['edit'])) { $operations['edit']['title'] = t('Edit vocabulary'); + $operations['edit']['weight'] = 0; } $operations['add'] = array( 'title' => t('Add terms'), 'weight' => 10, - 'url' => $entity->urlInfo('add-form'), + 'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), ); unset($operations['delete']);