diff --git a/core/lib/Drupal/Core/Form/ConfirmFormHelper.php b/core/lib/Drupal/Core/Form/ConfirmFormHelper.php index b58078d..764b8b8 100644 --- a/core/lib/Drupal/Core/Form/ConfirmFormHelper.php +++ b/core/lib/Drupal/Core/Form/ConfirmFormHelper.php @@ -36,7 +36,7 @@ public static function buildCancelLink(ConfirmFormInterface $form, Request $requ $options = UrlHelper::parse($query->get('destination')); // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is // resolved. - $url = Url::fromUri('base://' . $options['path'], $options); + $url = Url::fromUri('base://' . ltrim($options['path'], '/'), $options); } // Check for a route-based cancel link. else { diff --git a/core/modules/menu_link/menu_link.routing.yml b/core/modules/menu_link/menu_link.routing.yml new file mode 100644 index 0000000..8903009 --- /dev/null +++ b/core/modules/menu_link/menu_link.routing.yml @@ -0,0 +1,11 @@ +menu_link.delete: + path: /admin/structure/menu/menu_link/{menu_link_plugin}/delete + defaults: + _form: 'Drupal\menu_link\Plugin\Menu\Form\MenuLinkDeleteForm' + _title: 'Delete menu link' + options: + parameters: + menu_link_plugin: + type: menu_link_plugin + requirements: + _custom_access: 'Drupal\menu_link\Plugin\Menu\Form\MenuLinkDeleteForm::deleteAccess' diff --git a/core/modules/menu_link/src/Plugin/Menu/Form/MenulinkDeleteForm.php b/core/modules/menu_link/src/Plugin/Menu/Form/MenulinkDeleteForm.php new file mode 100644 index 0000000..c074283 --- /dev/null +++ b/core/modules/menu_link/src/Plugin/Menu/Form/MenulinkDeleteForm.php @@ -0,0 +1,161 @@ +moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('module_handler') + ); + } + + /** + * Checks access to this delete form. + * + * @param \Drupal\menu_link\Plugin\Menu\MenuLinkField $menu_link_plugin + * The menu link plugin + * + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. + */ + public function deleteAccess(MenuLinkField $menu_link_plugin) { + $entity = $menu_link_plugin->getEntity(); + return $entity->access('update', NULL, TRUE) + ->andIf($entity->{$menu_link_plugin->getFieldName()}->access('edit', NULL, TRUE)); + } + + /** + * {@inheritdoc} + */ + public function getBaseFormId() { + return 'menu_link_field_delete_confirm_form'; + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return $this->getBaseFormId(); + } + + /** + * {@inheritdoc} + */ + protected function prepareInvokeAll($hook, FormStateInterface $form_state) { + // Suppress hook invokation. + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state, MenuLinkField $menu_link_plugin = NULL) { + $this->entity = $menu_link_plugin->getEntity(); + $this->fieldName = $menu_link_plugin->getFieldName(); + $this->menuLinkPlugin = $menu_link_plugin; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->t('Are you sure you want to delete the menu link %title from the field %field ?', [ + '%title' => $this->menuLinkPlugin->getTitle(), + '%field' => $this->fieldName, + ]); + } + + /** + * {@inheritdoc} + */ + public function getCancelUrl() { + // Point to the entity of which this comment is a reply. + if ($this->moduleHandler->moduleExists('menu_ui')) { + return Url::fromRoute('entity.menu.edit_form', ['menu' => $this->entity->{$this->fieldName}->menu_name]); + } + return Url::fromRoute(''); + } + + /** + * {@inheritdoc} + */ + public function getDescription() { + return $this->t('The menu link will be removed from the menu. You can set it up later.'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $form_state->setRedirectUrl($this->getCancelUrl()); + + // Delete the comment and its replies. + $this->entity->{$this->fieldName}->menu_name = ''; + $this->entity->{$this->fieldName}->parent = ''; + $this->entity->{$this->fieldName}->title = ''; + $this->entity->{$this->fieldName}->description = ''; + $this->entity->save(); + + drupal_set_message($this->t('The menu link has been removed.'));; + } + +} \ No newline at end of file diff --git a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php index a1dfe75..21b8be6 100644 --- a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php +++ b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php @@ -12,6 +12,7 @@ use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Menu\MenuLinkBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -99,7 +100,7 @@ protected function getProperty($property) { if (!empty($this->pluginDefinition['metadata']['translatable']) && $this->languageManager->isMultilingual()) { /** @var \Drupal\Core\TypedData\TranslatableInterface|\Drupal\Core\Entity\EntityInterface $entity */ $entity = $this->entityManager->getTranslationFromContext($this->getEntity()); - $field_name = $this->getMetaData()['field_name']; + $field_name = $this->getFieldName(); if ($property_value = $entity->$field_name->$property) { return $property_value; } @@ -126,7 +127,7 @@ public function getWeight() { * {@inheritdoc} */ public function updateLink(array $new_definition_values, $persist) { - $field_name = $this->getMetaData()['field_name']; + $field_name = $this->getFieldName(); $this->pluginDefinition = $new_definition_values + $this->getPluginDefinition(); if ($persist) { @@ -173,7 +174,7 @@ public function isDeletable() { */ public function deleteLink() { $entity = $this->getEntity(); - $field_name = $this->getMetaData()['field_name']; + $field_name = $this->getFieldName(); $entity->$field_name->title = ''; $entity->$field_name->description = ''; @@ -181,5 +182,22 @@ public function deleteLink() { $entity->$field_name->parent = ''; } + /** + * {@inheritdoc} + */ + public function getDeleteRoute() { + return Url::fromRoute('menu_link.delete', [ + 'menu_link_plugin' => $this->getPluginId(), + ]); + } + + /** + * Returns the field name. + * + * @return string + */ + public function getFieldName() { + return $this->getPluginDefinition()['metadata']['field_name']; + } } diff --git a/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php b/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php new file mode 100644 index 0000000..96445ec --- /dev/null +++ b/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php @@ -0,0 +1,101 @@ +entityTypeId = 'node'; + $this->bundle = 'article'; + parent::setUp(); + + // Display the language selector. + $this->drupalLogin($this->administrator); + $edit = ['language_configuration[language_alterable]' => TRUE]; + $this->drupalPostForm("admin/structure/types/manage/{$this->bundle}", $edit, t('Save content type')); + $this->drupalLogin($this->translator); + } + + /** + * {@inheritdoc} + */ + protected function getEditorPermissions() { + return ['administer menu', 'administer nodes', "create $this->bundle content"]; + } + + /** + * {@inheritdoc} + */ + protected function getTranslatorPermissions() { + return array_merge(parent::getTranslatorPermissions(), ['administer menu', 'administer nodes', "edit any $this->bundle content"]); + } + + /** + * {@inheritdoc} + */ + protected function getAdministratorPermissions() { + return array_merge(parent::getAdministratorPermissions(), ['administer menu', 'access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access', 'administer languages', 'administer themes', 'view the administration theme']); + } + + /** + * {@inheritdoc} + */ + protected function getFormSubmitSuffix(EntityInterface $entity, $langcode) { + if (!$entity->isNew() && $entity->isTranslatable()) { + $translations = $entity->getTranslationLanguages(); + if ((count($translations) > 1 || !isset($translations[$langcode])) && ($field = $entity->getFieldDefinition('status'))) { + return ' ' . ($field->isTranslatable() ? t('(this translation)') : t('(all translations)')); + } + } + return ''; + } + + /** + * {@inheritdoc} + */ + protected function getFormSubmitAction(EntityInterface $entity, $langcode) { + if ($entity->getTranslation($langcode)->isPublished()) { + return t('Save and keep published') . $this->getFormSubmitSuffix($entity, $langcode); + } + else { + return t('Save and keep unpublished') . $this->getFormSubmitSuffix($entity, $langcode); + } + } + +}