Commit e772e1fc authored by webchick's avatar webchick

Issue #2486177 by disasm, amateescu, plach, Pere Orga, piyuesh23, webchick,...

Issue #2486177 by disasm, amateescu, plach, Pere Orga, piyuesh23, webchick, Saphyel, dawehner, jibran, YesCT, yched, xjm, Gábor Hojtsy, Bojhan: Deleting an entity translation from the UI deletes the whole entity
parent e0c9d38e
......@@ -7,11 +7,141 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides a generic base class for a content entity deletion form.
*
* @todo Re-evaluate and streamline the entity deletion form class hierarchy in
* https://www.drupal.org/node/2491057.
*/
class ContentEntityDeleteForm extends ContentEntityConfirmFormBase {
use EntityDeleteFormTrait;
use EntityDeleteFormTrait {
getQuestion as traitGetQuestion;
logDeletionMessage as traitLogDeletionMessage;
getDeletionMessage as traitGetDeletionMessage;
getCancelUrl as traitGetCancelUrl;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
if ($entity->isDefaultTranslation()) {
if (count($entity->getTranslationLanguages()) > 1) {
$languages = [];
foreach ($entity->getTranslationLanguages() as $language) {
$languages[] = $language->getName();
}
$form['deleted_translations'] = array(
'#theme' => 'item_list',
'#title' => $this->t('The following @entity-type translations will be deleted:', [
'@entity-type' => $entity->getEntityType()->getLowercaseLabel()
]),
'#items' => $languages,
);
$form['actions']['submit']['#value'] = $this->t('Delete all translations');
}
}
else {
$form['actions']['submit']['#value'] = $this->t('Delete @language translation', array('@language' => $entity->language()->getName()));
}
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
// Make sure that deleting a translation does not delete the whole entity.
if (!$entity->isDefaultTranslation()) {
$untranslated_entity = $entity->getUntranslated();
$untranslated_entity->removeTranslation($entity->language()->getId());
$untranslated_entity->save();
$form_state->setRedirectUrl($untranslated_entity->urlInfo('canonical'));
}
else {
$entity->delete();
$form_state->setRedirectUrl($this->getRedirectUrl());
}
drupal_set_message($this->getDeletionMessage());
$this->logDeletionMessage();
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
return $entity->isDefaultTranslation() ? $this->traitGetCancelUrl() : $entity->urlInfo('canonical');
}
/**
* {@inheritdoc}
*/
protected function getDeletionMessage() {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
if (!$entity->isDefaultTranslation()) {
return $this->t('The @entity-type %label @language translation has been deleted.', [
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
'%label' => $entity->label(),
'@language' => $entity->language()->getName(),
]);
}
return $this->traitGetDeletionMessage();
}
/**
* {@inheritdoc}
*/
protected function logDeletionMessage() {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
if (!$entity->isDefaultTranslation()) {
$this->logger($entity->getEntityType()->getProvider())->notice('The @entity-type %label @language translation has been deleted.', [
'@entity-type' => $entity->getEntityType()->getLowercaseLabel(),
'%label' => $entity->label(),
'@language' => $entity->language()->getName(),
]);
}
else {
$this->traitLogDeletionMessage();
}
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->getEntity();
if (!$entity->isDefaultTranslation()) {
return $this->t('Are you sure you want to delete the @language translation of the @entity-type %label?', array(
'@language' => $entity->language()->getName(),
'@entity-type' => $this->getEntity()->getEntityType()->getLowercaseLabel(),
'%label' => $this->getEntity()->label(),
));
}
return $this->traitGetQuestion();
}
}
......@@ -9,6 +9,7 @@
use Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
/**
* Provides a trait for an entity deletion form.
......@@ -90,6 +91,24 @@ public function getCancelUrl() {
}
}
/**
* Returns the URL where the user should be redirected after deletion.
*
* @return \Drupal\Core\Url
* The redirect URL.
*/
protected function getRedirectUrl() {
$entity = $this->getEntity();
if ($entity->hasLinkTemplate('collection')) {
// If available, return the collection URL.
return $entity->urlInfo('collection');
}
else {
// Otherwise fall back to the front page.
return Url::fromRoute('<front>');
}
}
/**
* Logs a message about the deleted entity.
*/
......
......@@ -54,6 +54,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->getConfirmText(),
'#button_type' => 'primary',
);
$form['actions']['cancel'] = ConfirmFormHelper::buildCancelLink($this, $this->getRequest());
......
......@@ -22,6 +22,13 @@ public function getCancelUrl() {
return new Url('aggregator.admin_overview');
}
/**
* {@inheritdoc}
*/
protected function getRedirectUrl() {
return $this->getCancelUrl();
}
/**
* {@inheritdoc}
*/
......
......@@ -8,7 +8,6 @@
namespace Drupal\comment\Form;
use Drupal\Core\Entity\ContentEntityDeleteForm;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides the comment delete confirmation form.
......@@ -23,6 +22,13 @@ public function getCancelUrl() {
return $this->entity->get('entity_id')->entity->urlInfo();
}
/**
* {@inheritdoc}
*/
protected function getRedirectUrl() {
return $this->getCancelUrl();
}
/**
* {@inheritdoc}
*/
......
......@@ -127,6 +127,9 @@ function content_translation_entity_type_alter(array &$entity_types) {
if (!$entity_type->get('content_translation_metadata')) {
$entity_type->set('content_translation_metadata', 'Drupal\content_translation\ContentTranslationMetadataWrapper');
}
if (!$entity_type->getFormClass('content_translation_deletion')) {
$entity_type->setFormClass('content_translation_deletion', '\Drupal\content_translation\Form\ContentTranslationDeleteForm');
}
$translation = $entity_type->get('translation');
if (!$translation || !isset($translation['content_translation'])) {
......@@ -277,8 +280,10 @@ function content_translation_form_alter(array &$form, FormStateInterface $form_s
return;
}
$entity = $form_object->getEntity();
$op = $form_object->getOperation();
if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && count($entity->getTranslationLanguages()) > 1) {
// Let the content translation handler alter the content entity edit form.
if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && count($entity->getTranslationLanguages()) > 1 && ($op == 'edit' || $op == 'default')) {
$controller = \Drupal::entityManager()->getHandler($entity->getEntityTypeId(), 'translation');
$controller->entityFormAlter($form, $form_state, $entity);
......
......@@ -73,13 +73,28 @@ public function __construct(EntityManagerInterface $manager, LanguageManagerInte
public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL, $entity_type_id = NULL) {
/* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
if ($entity = $route_match->getParameter($entity_type_id)) {
$operation = $route->getRequirement('_access_content_translation_manage');
$language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
$entity_type = $this->entityManager->getDefinition($entity_type_id);
if (in_array($operation, ['update', 'delete'])) {
// Translation operations cannot be performed on the default
// translation.
if ($language->getId() == $entity->getUntranslated()->language()->getId()) {
return AccessResult::forbidden()->cacheUntilEntityChanges($entity);
}
// Editors have no access to the translation operations, as entity
// access already grants them an equal or greater access level.
$templates = ['update' => 'edit-form', 'delete' => 'delete-form'];
if ($entity->access($operation) && $entity_type->hasLinkTemplate($templates[$operation])) {
return AccessResult::forbidden()->cachePerPermissions();
}
}
if ($account->hasPermission('translate any entity')) {
return AccessResult::allowed()->cachePerPermissions();
}
$operation = $route->getRequirement('_access_content_translation_manage');
/* @var \Drupal\content_translation\ContentTranslationHandlerInterface $handler */
$handler = $this->entityManager->getHandler($entity->getEntityTypeId(), 'translation');
......@@ -98,9 +113,8 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
return AccessResult::allowedIf($is_new_translation)->cachePerPermissions()->cacheUntilEntityChanges($entity)
->andIf($handler->getTranslationAccess($entity, $operation));
case 'update':
case 'delete':
$language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
case 'update':
$has_translation = isset($languages[$language->getId()])
&& $language->getId() != $entity->getUntranslated()->language()->getId()
&& isset($translations[$language->getId()]);
......
......@@ -319,12 +319,13 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
break;
}
}
$access = $this->getTranslationAccess($entity, 'delete')->isAllowed() || ($entity->access('delete') && $this->entityType->hasLinkTemplate('delete-form'));
$form['actions']['delete_translation'] = array(
'#type' => 'submit',
'#value' => t('Delete translation'),
'#weight' => $weight,
'#submit' => array(array($this, 'entityFormDeleteTranslation')),
'#access' => $this->getTranslationAccess($entity, 'delete')->isAllowed(),
'#access' => $access,
);
}
......@@ -607,13 +608,20 @@ function entityFormDelete($form, FormStateInterface $form_state) {
* Takes care of content translation deletion.
*/
function entityFormDeleteTranslation($form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */
$form_object = $form_state->getFormObject();
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $form_object->getEntity();
$entity_type_id = $entity->getEntityTypeId();
$form_state->setRedirect('content_translation.translation_delete_' . $entity_type_id, array(
if ($entity->access('delete') && $this->entityType->hasLinkTemplate('delete-form')) {
$form_state->setRedirectUrl($entity->urlInfo('delete-form'));
}
else {
$form_state->setRedirect('content_translation.translation_delete_' . $entity_type_id, [
$entity_type_id => $entity->id(),
'language' => $form_object->getFormLangcode($form_state),
));
]);
}
}
/**
......
......@@ -71,10 +71,12 @@ public function prepareTranslation(ContentEntityInterface $entity, LanguageInter
* Array of page elements to render.
*/
public function overview(RouteMatchInterface $route_match, $entity_type_id = NULL) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $route_match->getParameter($entity_type_id);
$account = $this->currentUser();
$handler = $this->entityManager()->getHandler($entity_type_id, 'translation');
$manager = $this->manager;
$entity_type = $entity->getEntityType();
$languages = $this->languageManager()->getLanguages();
$original = $entity->getUntranslated()->language()->getId();
......@@ -164,7 +166,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
// If the user is allowed to edit the entity we point the edit link to
// the entity form, otherwise if we are not dealing with the original
// language we point the link to the translation form.
if ($entity->access('update')) {
if ($entity->access('update') && $entity_type->hasLinkTemplate('edit-form')) {
$links['edit']['url'] = $entity->urlInfo('edit-form');
$links['edit']['language'] = $language;
}
......@@ -190,7 +192,14 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
}
else {
$source_name = isset($languages[$source]) ? $languages[$source]->getName() : $this->t('n/a');
if ($handler->getTranslationAccess($entity, 'delete')->isAllowed()) {
if ($entity->access('delete') && $entity_type->hasLinkTemplate('delete-form')) {
$links['delete'] = array(
'title' => $this->t('Delete'),
'url' => $entity->urlInfo('delete-form'),
'language' => $language,
);
}
elseif ($handler->getTranslationAccess($entity, 'delete')->isAllowed()) {
$links['delete'] = array(
'title' => $this->t('Delete'),
'url' => $delete_url,
......
......@@ -7,29 +7,14 @@
namespace Drupal\content_translation\Form;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Entity\ContentEntityDeleteForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
/**
* Delete translation form for content_translation module.
*/
class ContentTranslationDeleteForm extends ConfirmFormBase {
/**
* The entity whose translation is being deleted.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;
/**
* The language of the translation being deleted.
*
* @var \Drupal\Core\Language\LanguageInterface
*/
protected $language;
class ContentTranslationDeleteForm extends ContentEntityDeleteForm {
/**
* {@inheritdoc}
......@@ -41,43 +26,11 @@ public function getFormId() {
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL, LanguageInterface $language = NULL) {
$this->entity = $this->getRouteMatch()->getParameter($entity_type_id);
$this->language = $language;
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function getConfirmText() {
return $this->t('Delete');
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to delete the @language translation of %label?', array('@language' => $this->language->getName(), '%label' => $this->entity->label()));
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
return $this->entity->urlInfo('drupal:content-translation-overview');
public function buildForm(array $form, FormStateInterface $form_state, LanguageInterface $language = NULL) {
if ($language) {
$form_state->set('langcode', $language->getId());
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Remove the translated values.
$this->entity = $this->entity->getUntranslated();
$this->entity->removeTranslation($this->language->getId());
$this->entity->save();
$form_state->setRedirectUrl($this->getCancelUrl());
return parent::buildForm($form, $form_state);
}
}
......@@ -141,7 +141,7 @@ protected function alterRoutes(RouteCollection $collection) {
$route = new Route(
$path . '/delete/{language}',
array(
'_form' => '\Drupal\content_translation\Form\ContentTranslationDeleteForm',
'_entity_form' => $entity_type_id . '.content_translation_deletion',
'language' => NULL,
'_title' => 'Delete',
'entity_type_id' => $entity_type_id,
......
......@@ -253,16 +253,23 @@ protected function doTestAuthoringInfo() {
*/
protected function doTestTranslationDeletion() {
// Confirm and delete a translation.
$this->drupalLogin($this->translator);
$langcode = 'fr';
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
$url = $entity->urlInfo('edit-form', array('language' => ConfigurableLanguage::load($langcode)));
$language = ConfigurableLanguage::load($langcode);
$url = $entity->urlInfo('edit-form', array('language' => $language));
$this->drupalPostForm($url, array(), t('Delete translation'));
$this->drupalPostForm(NULL, array(), t('Delete'));
$this->drupalPostForm(NULL, array(), t('Delete @language translation', array('@language' => $language->getName())));
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
if ($this->assertTrue(is_object($entity), 'Entity found')) {
$translations = $entity->getTranslationLanguages();
$this->assertTrue(count($translations) == 2 && empty($translations[$langcode]), 'Translation successfully deleted.');
}
// Check that the translator cannot delete the original translation.
$args = [$this->entityTypeId => $entity->id(), 'language' => 'en'];
$this->drupalGet(Url::fromRoute('content_translation.translation_delete_' . $this->entityTypeId, $args));
$this->assertResponse(403);
}
/**
......
......@@ -7,6 +7,7 @@
namespace Drupal\content_translation\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\user\UserInterface;
......@@ -72,16 +73,37 @@ protected function setupEntity() {
*/
function testWorkflows() {
// Test workflows for the editor.
$expected_status = array('edit' => 200, 'overview' => 403, 'add_translation' => 403, 'edit_translation' => 403);
$this->assertWorkflows($this->editor, $expected_status);
$expected_status = [
'edit' => 200,
'delete' => 200,
'overview' => 403,
'add_translation' => 403,
'edit_translation' => 403,
'delete_translation' => 403,
];
$this->doTestWorkflows($this->editor, $expected_status);
// Test workflows for the translator.
$expected_status = array('edit' => 403, 'overview' => 200, 'add_translation' => 200, 'edit_translation' => 200);
$this->assertWorkflows($this->translator, $expected_status);
$expected_status = [
'edit' => 403,
'delete' => 403,
'overview' => 200,
'add_translation' => 200,
'edit_translation' => 200,
'delete_translation' => 200,
];
$this->doTestWorkflows($this->translator, $expected_status);
// Test workflows for the admin.
$expected_status = array('edit' => 200, 'overview' => 200, 'add_translation' => 200, 'edit_translation' => 200);
$this->assertWorkflows($this->administrator, $expected_status);
$expected_status = [
'edit' => 200,
'delete' => 200,
'overview' => 200,
'add_translation' => 200,
'edit_translation' => 403,
'delete_translation' => 403,
];
$this->doTestWorkflows($this->administrator, $expected_status);
// Check that translation permissions allow the associated operations.
$ops = array('create' => t('Add'), 'update' => t('Edit'), 'delete' => t('Delete'));
......@@ -111,30 +133,35 @@ function testWorkflows() {
* The an associative array with the operation name as key and the expected
* status as value.
*/
protected function assertWorkflows(UserInterface $user, $expected_status) {
protected function doTestWorkflows(UserInterface $user, $expected_status) {
$default_langcode = $this->langcodes[0];
$languages = $this->container->get('language_manager')->getLanguages();
$args = array('@user_label' => $user->getUsername());
$args = ['@user_label' => $user->getUsername()];
$options = ['language' => $languages[$default_langcode], 'absolute' => TRUE];
$this->drupalLogin($user);
// Check whether the user is allowed to access the entity form in edit mode.
$options = array('language' => $languages[$default_langcode], 'absolute' => TRUE);
$edit_url = $this->entity->urlInfo('edit-form', $options);
$this->drupalGet($edit_url, $options);
$this->assertResponse($expected_status['edit'], format_string('The @user_label has the expected edit access.', $args));
$this->assertResponse($expected_status['edit'], SafeMarkup::format('The @user_label has the expected edit access.', $args));
// Check whether the user is allowed to access the entity delete form.
$delete_url = $this->entity->urlInfo('delete-form', $options);
$this->drupalGet($delete_url, $options);
$this->assertResponse($expected_status['delete'], SafeMarkup::format('The @user_label has the expected delete access.', $args));
// Check whether the user is allowed to access the translation overview.
$langcode = $this->langcodes[1];
$options = array('language' => $languages[$langcode], 'absolute' => TRUE);
$options['language'] = $languages[$langcode];
$translations_url = $this->entity->url('drupal:content-translation-overview', $options);
$this->drupalGet($translations_url);
$this->assertResponse($expected_status['overview'], format_string('The @user_label has the expected translation overview access.', $args));
$this->assertResponse($expected_status['overview'], SafeMarkup::format('The @user_label has the expected translation overview access.', $args));
// Check whether the user is allowed to create a translation.
$add_translation_url = Url::fromRoute('content_translation.translation_add_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $langcode], $options);
if ($expected_status['add_translation'] == 200) {
$this->clickLink('Add');
$this->assertUrl($add_translation_url->toString(), array(), 'The translation overview points to the translation form when creating translations.');
$this->assertUrl($add_translation_url->toString(), [], 'The translation overview points to the translation form when creating translations.');
// Check that the translation form does not contain shared elements for
// translators.
if ($expected_status['edit'] == 403) {
......@@ -144,13 +171,12 @@ protected function assertWorkflows(UserInterface $user, $expected_status) {
else {
$this->drupalGet($add_translation_url);
}
$this->assertResponse($expected_status['add_translation'], format_string('The @user_label has the expected translation creation access.', $args));
$this->assertResponse($expected_status['add_translation'], SafeMarkup::format('The @user_label has the expected translation creation access.', $args));
// Check whether the user is allowed to edit a translation.
$langcode = $this->langcodes[2];
$options['language'] = $languages[$langcode];
$edit_translation_url = Url::fromRoute('content_translation.translation_edit_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
$options = ['language' => $languages[$langcode], 'absolute' => TRUE];
if ($expected_status['edit_translation'] == 200) {
$this->drupalGet($translations_url);
$editor = $expected_status['edit'] == 200;
......@@ -158,7 +184,6 @@ protected function assertWorkflows(UserInterface $user, $expected_status) {
if ($editor) {
$this->clickLink('Edit', 2);
// An editor should be pointed to the entity form in multilingual mode.
// We need a new expected edit path with a new language.
$expected_edit_path = $this->entity->url('edit-form', $options);
$this->assertUrl($expected_edit_path, [], 'The translation overview points to the edit form for editors when editing translations.');
......@@ -166,7 +191,7 @@ protected function assertWorkflows(UserInterface $user, $expected_status) {
else {
$this->clickLink('Edit');
// While a translator should be pointed to the translation form.
$this->assertUrl($edit_translation_url->toString(), array(), 'The translation overview points to the translation form for translators when editing translations.');
$this->assertUrl($edit_translation_url->toString(), [], 'The translation overview points to the translation form for translators when editing translations.');
// Check that the translation form does not contain shared elements.
$this->assertNoSharedElements();
}
......@@ -174,7 +199,35 @@ protected function assertWorkflows(UserInterface $user, $expected_status) {
else {
$this->drupalGet($edit_translation_url);
}
$this->assertResponse($expected_status['edit_translation'], format_string('The @user_label has the expected translation creation access.', $args));
$this->assertResponse($expected_status['edit_translation'], SafeMarkup::format('The @user_label has the expected translation edit access.', $args));
// Check whether the user is allowed to delete a translation.
$langcode = $this->langcodes[2];
$options['language'] = $languages[$langcode];
$delete_translation_url = Url::fromRoute('content_translation.translation_delete_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
if ($expected_status['delete_translation'] == 200) {
$this->drupalGet($translations_url);
$editor = $expected_status['delete'] == 200;
if ($editor) {
$this->clickLink('Delete', 2);
// An editor should be pointed to the entity deletion form in
// multilingual mode. We need a new expected delete path with a new
// language.
$expected_delete_path = $this->entity->url('delete-form', $options);
$this->assertUrl($expected_delete_path, [], 'The translation overview points to the delete form for editors when deleting translations.');
}
else {
$this->clickLink('Delete');
// While a translator should be pointed to the translation deletion
// form.
$this->assertUrl($delete_translation_url->toString(), [], 'The translation overview points to the translation deletion form for translators when deleting translations.');
}
}
else {
$this->drupalGet($delete_translation_url);
}
$this->assertResponse($expected_status['delete_translation'], SafeMarkup::format('The @user_label has the expected translation deletion access.', $args));
}
/**
......
......@@ -47,13 +47,17 @@ public function testCreateAccess() {
// Set the mock language manager.
$language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
$language_manager->expects($this->at(0))
->method('getLanguage')
->with($this->equalTo($source))
->will($this->returnValue(new Language(array('id' => 'en'))));
$language_manager->expects($this->at(1))
->method('getLanguages')
->will($this->returnValue(array('en' => array(), 'it' => array())));
$language_manager->expects($this->at(1))
$language_manager->expects($this->at(2))
->method('getLanguage')
->with($this->equalTo($source))
->will($this->returnValue(new Language(array('id' => 'en'))));
$language_manager->expects($this->at(2))
$language_manager->expects($this->at(3))
->method('getLanguage')
->with($this->equalTo($target))
->will($this->returnValue(new Language(array('id' => 'it'))));
......
......@@ -22,6 +22,13 @@ public function getCancelUrl() {
return new Url('entity.menu.edit_form', array('menu' => $this->entity->getMenuName()));
}
/**
* {@inheritdoc}
*/
protected function getRedirectUrl() {
return $this->getCancelUrl();
}
/**
* {@inheritdoc}