Commit 5ad8f598 authored by plach's avatar plach

Issue #2880152 by amateescu, blazey, plach, larowlan, vijaycs85: Convert...

Issue #2880152 by amateescu, blazey, plach, larowlan, vijaycs85: Convert custom menu links to be revisionable
parent 1e0ad95a
......@@ -29,6 +29,16 @@ function menu_link_content_help($route_name, RouteMatchInterface $route_match) {
}
}
/**
* Implements hook_entity_type_alter().
*/
function menu_link_content_entity_type_alter(array &$entity_types) {
// @todo Moderation is disabled for custom menu links until when we have an UI
// for them.
// @see https://www.drupal.org/project/drupal/issues/2350939
$entity_types['menu_link_content']->setHandlerClass('moderation', '');
}
/**
* Implements hook_menu_delete().
*/
......
<?php
/**
* @file
* Post update functions for the Menu link content module.
*/
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Update custom menu links to be revisionable.
*/
function menu_link_content_post_update_make_menu_link_content_revisionable(&$sandbox) {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
/** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */
$last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
$entity_type = $definition_update_manager->getEntityType('menu_link_content');
$field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('menu_link_content');
// Update the entity type definition.
$entity_keys = $entity_type->getKeys();
$entity_keys['revision'] = 'revision_id';
$entity_keys['revision_translation_affected'] = 'revision_translation_affected';
$entity_type->set('entity_keys', $entity_keys);
$entity_type->set('revision_table', 'menu_link_content_revision');
$entity_type->set('revision_data_table', 'menu_link_content_field_revision');
$revision_metadata_keys = [
'revision_default' => 'revision_default',
'revision_user' => 'revision_user',
'revision_created' => 'revision_created',
'revision_log_message' => 'revision_log_message',
];
$entity_type->set('revision_metadata_keys', $revision_metadata_keys);
// Update the field storage definitions and add the new ones required by a
// revisionable entity type.
$field_storage_definitions['langcode']->setRevisionable(TRUE);
$field_storage_definitions['title']->setRevisionable(TRUE);
$field_storage_definitions['description']->setRevisionable(TRUE);
$field_storage_definitions['link']->setRevisionable(TRUE);
$field_storage_definitions['external']->setRevisionable(TRUE);
$field_storage_definitions['enabled']->setRevisionable(TRUE);
$field_storage_definitions['changed']->setRevisionable(TRUE);
$field_storage_definitions['revision_id'] = BaseFieldDefinition::create('integer')
->setName('revision_id')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Revision ID'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
$field_storage_definitions['revision_default'] = BaseFieldDefinition::create('boolean')
->setName('revision_default')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Default revision'))
->setDescription(new TranslatableMarkup('A flag indicating whether this was a default revision when it was saved.'))
->setStorageRequired(TRUE)
->setInternal(TRUE)
->setTranslatable(FALSE)
->setRevisionable(TRUE);
$field_storage_definitions['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
->setName('revision_translation_affected')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Revision translation affected'))
->setDescription(new TranslatableMarkup('Indicates if the last edit of a translation belongs to current revision.'))
->setReadOnly(TRUE)
->setRevisionable(TRUE)
->setTranslatable(TRUE);
$field_storage_definitions['revision_created'] = BaseFieldDefinition::create('created')
->setName('revision_created')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Revision create time'))
->setDescription(new TranslatableMarkup('The time that the current revision was created.'))
->setRevisionable(TRUE);
$field_storage_definitions['revision_user'] = BaseFieldDefinition::create('entity_reference')
->setName('revision_user')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Revision user'))
->setDescription(new TranslatableMarkup('The user ID of the author of the current revision.'))
->setSetting('target_type', 'user')
->setRevisionable(TRUE);
$field_storage_definitions['revision_log_message'] = BaseFieldDefinition::create('string_long')
->setName('revision_log_message')
->setTargetEntityTypeId('menu_link_content')
->setTargetBundle(NULL)
->setLabel(new TranslatableMarkup('Revision log message'))
->setDescription(new TranslatableMarkup('Briefly describe the changes you have made.'))
->setRevisionable(TRUE)
->setDefaultValue('');
$definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);
return t('Custom menu links have been converted to be revisionable.');
}
......@@ -2,9 +2,7 @@
namespace Drupal\menu_link_content\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityPublishedTrait;
use Drupal\Core\Entity\EditorialContentEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
......@@ -28,7 +26,7 @@
* plural = "@count custom menu links",
* ),
* handlers = {
* "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
* "storage" = "\Drupal\menu_link_content\MenuLinkContentStorage",
* "storage_schema" = "Drupal\menu_link_content\MenuLinkContentStorageSchema",
* "access" = "Drupal\menu_link_content\MenuLinkContentAccessControlHandler",
* "form" = {
......@@ -39,26 +37,34 @@
* admin_permission = "administer menu",
* base_table = "menu_link_content",
* data_table = "menu_link_content_data",
* revision_table = "menu_link_content_revision",
* revision_data_table = "menu_link_content_field_revision",
* translatable = TRUE,
* entity_keys = {
* "id" = "id",
* "revision" = "revision_id",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid",
* "bundle" = "bundle",
* "published" = "enabled",
* },
* revision_metadata_keys = {
* "revision_user" = "revision_user",
* "revision_created" = "revision_created",
* "revision_log_message" = "revision_log_message",
* },
* links = {
* "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
* "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
* "delete-form" = "/admin/structure/menu/item/{menu_link_content}/delete",
* }
* },
* constraints = {
* "MenuTreeHierarchy" = {}
* },
* )
*/
class MenuLinkContent extends ContentEntityBase implements MenuLinkContentInterface {
use EntityChangedTrait;
use EntityPublishedTrait;
class MenuLinkContent extends EditorialContentEntityBase implements MenuLinkContentInterface {
/**
* A flag for whether this entity is wrapped in a plugin instance.
......@@ -203,6 +209,11 @@ public function preSave(EntityStorageInterface $storage) {
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
// Don't update the menu tree if a pending revision was saved.
if (!$this->isDefaultRevision()) {
return;
}
/** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
......@@ -277,6 +288,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setDescription(t('The text to be used for this link in the menu.'))
->setRequired(TRUE)
->setTranslatable(TRUE)
->setRevisionable(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'hidden',
......@@ -293,6 +305,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setLabel(t('Description'))
->setDescription(t('Shown when hovering over the menu link.'))
->setTranslatable(TRUE)
->setRevisionable(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'hidden',
......@@ -313,6 +326,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['link'] = BaseFieldDefinition::create('link')
->setLabel(t('Link'))
->setDescription(t('The location this menu link points to.'))
->setRevisionable(TRUE)
->setRequired(TRUE)
->setSettings([
'link_type' => LinkItemInterface::LINK_GENERIC,
......@@ -326,7 +340,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['external'] = BaseFieldDefinition::create('boolean')
->setLabel(t('External'))
->setDescription(t('A flag to indicate if the link points to a full URL starting with a protocol, like http:// (1 = external, 0 = internal).'))
->setDefaultValue(FALSE);
->setDefaultValue(FALSE)
->setRevisionable(TRUE);
$fields['rediscover'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Indicates whether the menu link should be rediscovered'))
......@@ -365,7 +380,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['enabled']->setLabel(t('Enabled'));
$fields['enabled']->setDescription(t('A flag for whether the link should be enabled in menus or hidden.'));
$fields['enabled']->setTranslatable(FALSE);
$fields['enabled']->setRevisionable(FALSE);
$fields['enabled']->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'boolean',
......@@ -383,7 +397,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the menu link was last edited.'))
->setTranslatable(TRUE);
->setTranslatable(TRUE)
->setRevisionable(TRUE);
// @todo Keep this field hidden until we have a revision UI for menu links.
// @see https://www.drupal.org/project/drupal/issues/2350939
$fields['revision_log_message']->setDisplayOptions('form', [
'region' => 'hidden',
]);
return $fields;
}
......
......@@ -127,19 +127,11 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
public function save(array $form, FormStateInterface $form_state) {
// The entity is rebuilt in parent::submit().
$menu_link = $this->entity;
$saved = $menu_link->save();
if ($saved) {
$this->messenger()->addStatus($this->t('The menu link has been saved.'));
$form_state->setRedirect(
'entity.menu_link_content.canonical',
['menu_link_content' => $menu_link->id()]
);
}
else {
$this->messenger()->addError($this->t('There was an error saving the menu link.'));
$form_state->setRebuild();
}
$menu_link->save();
$this->messenger()->addStatus($this->t('The menu link has been saved.'));
$form_state->setRedirectUrl($menu_link->toUrl('canonical'));
}
}
......@@ -5,11 +5,12 @@
use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\RevisionLogInterface;
/**
* Defines an interface for custom menu links.
*/
interface MenuLinkContentInterface extends ContentEntityInterface, EntityChangedInterface, EntityPublishedInterface {
interface MenuLinkContentInterface extends ContentEntityInterface, EntityChangedInterface, EntityPublishedInterface, RevisionLogInterface {
/**
* Flags this instance as being wrapped in a menu link plugin instance.
......
<?php
namespace Drupal\menu_link_content;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
/**
* Storage handler for menu_link_content entities.
*/
class MenuLinkContentStorage extends SqlContentEntityStorage implements MenuLinkContentStorageInterface {
/**
* {@inheritdoc}
*/
public function getMenuLinkIdsWithPendingRevisions() {
$table_mapping = $this->getTableMapping();
$id_field = $table_mapping->getColumnNames($this->entityType->getKey('id'))['value'];
$revision_field = $table_mapping->getColumnNames($this->entityType->getKey('revision'))['value'];
$rta_field = $table_mapping->getColumnNames($this->entityType->getKey('revision_translation_affected'))['value'];
$langcode_field = $table_mapping->getColumnNames($this->entityType->getKey('langcode'))['value'];
$revision_default_field = $table_mapping->getColumnNames($this->entityType->getRevisionMetadataKey('revision_default'))['value'];
$query = $this->database->select($this->getRevisionDataTable(), 'mlfr');
$query->fields('mlfr', [$id_field]);
$query->addExpression("MAX(mlfr.$revision_field)", $revision_field);
$query->join($this->getRevisionTable(), 'mlr', "mlfr.$revision_field = mlr.$revision_field AND mlr.$revision_default_field = 0");
$inner_select = $this->database->select($this->getRevisionDataTable(), 't');
$inner_select->condition("t.$rta_field", '1');
$inner_select->fields('t', [$id_field, $langcode_field]);
$inner_select->addExpression("MAX(t.$revision_field)", $revision_field);
$inner_select
->groupBy("t.$id_field")
->groupBy("t.$langcode_field");
$query->join($inner_select, 'mr', "mlfr.$revision_field = mr.$revision_field AND mlfr.$langcode_field = mr.$langcode_field");
$query->groupBy("mlfr.$id_field");
return $query->execute()->fetchAllKeyed(1, 0);
}
}
<?php
namespace Drupal\menu_link_content;
use Drupal\Core\Entity\ContentEntityStorageInterface;
/**
* Defines an interface for menu_link_content entity storage classes.
*/
interface MenuLinkContentStorageInterface extends ContentEntityStorageInterface {
/**
* Gets a list of menu link IDs with pending revisions.
*
* @return int[]
* An array of menu link IDs which have pending revisions, keyed by their
* revision IDs.
*
* @internal
*/
public function getMenuLinkIdsWithPendingRevisions();
}
<?php
namespace Drupal\menu_link_content\Plugin\Validation\Constraint;
use Drupal\Core\Entity\Plugin\Validation\Constraint\CompositeConstraintBase;
/**
* Validation constraint for changing the menu hierarchy in pending revisions.
*
* @Constraint(
* id = "MenuTreeHierarchy",
* label = @Translation("Menu tree hierarchy.", context = "Validation"),
* )
*/
class MenuTreeHierarchyConstraint extends CompositeConstraintBase {
/**
* The default violation message.
*
* @var string
*/
public $message = 'You can only change the hierarchy for the <em>published</em> version of this menu link.';
/**
* {@inheritdoc}
*/
public function coversFields() {
return ['parent', 'weight'];
}
}
<?php
namespace Drupal\menu_link_content\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Constraint validator for changing menu link parents in pending revisions.
*/
class MenuTreeHierarchyConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
private $entityTypeManager;
/**
* Creates a new MenuTreeHierarchyConstraintValidator instance.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function validate($entity, Constraint $constraint) {
if ($entity && !$entity->isNew() && !$entity->isDefaultRevision()) {
$original = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
// Ensure that empty items do not affect the comparison checks below.
// @todo Remove this filtering when
// https://www.drupal.org/project/drupal/issues/3039031 is fixed.
$entity->parent->filterEmptyItems();
if (($entity->parent->isEmpty() !== $original->parent->isEmpty()) || !$entity->parent->equals($original->parent)) {
$this->context->buildViolation($constraint->message)
->atPath('menu_parent')
->addViolation();
}
if (!$entity->weight->equals($original->weight)) {
$this->context->buildViolation($constraint->message)
->atPath('weight')
->addViolation();
}
}
}
}
......@@ -120,6 +120,11 @@ protected function getExpectedNormalizedEntity() {
'value' => 1,
],
],
'revision_id' => [
[
'value' => 1,
],
],
'title' => [
[
'value' => 'Llama Gabilondo',
......@@ -191,6 +196,16 @@ protected function getExpectedNormalizedEntity() {
],
],
'parent' => [],
'revision_created' => [
$this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()),
],
'revision_user' => [],
'revision_log_message' => [],
'revision_translation_affected' => [
[
'value' => TRUE,
],
],
];
}
......
......@@ -59,6 +59,49 @@ public function testPublishedEntityKeyAddition() {
$this->assertTrue($menu_link->isPublished());
}
/**
* Tests the conversion of custom menu links to be revisionable.
*
* @see menu_link_content_post_update_make_menu_link_content_revisionable()
*/
public function testConversionToRevisionable() {
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('menu_link_content');
$this->assertFalse($entity_type->isRevisionable());
$this->runUpdates();
$entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('menu_link_content');
$this->assertTrue($entity_type->isRevisionable());
// Log in as user 1.
$account = User::load(1);
$account->passRaw = 'drupal';
$this->drupalLogin($account);
// Make sure our custom menu link exists.
$assert_session = $this->assertSession();
$this->drupalGet('admin/structure/menu/item/1/edit');
$assert_session->checkboxChecked('edit-enabled-value');
// Check that custom menu links can be created, saved and then loaded.
$storage = \Drupal::entityTypeManager()->getStorage('menu_link_content');
/** @var \Drupal\menu_link_content\Entity\MenuLinkContent $menu_link */
$menu_link = $storage->create([
'menu_name' => 'main',
'link' => 'route:user.page',
'title' => 'Pineapple',
]);
$menu_link->save();
$storage->resetCache();
$menu_link = $storage->loadRevision($menu_link->getRevisionId());
$this->assertEquals('main', $menu_link->getMenuName());
$this->assertEquals('Pineapple', $menu_link->label());
$this->assertEquals('route:user.page', $menu_link->link->uri);
$this->assertTrue($menu_link->isPublished());
}
/**
* {@inheritdoc}
*/
......
......@@ -18,7 +18,7 @@ class MenuLinkContentDeriverTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['menu_link_content', 'link', 'system', 'menu_link_content_dynamic_route'];
public static $modules = ['menu_link_content', 'link', 'system', 'menu_link_content_dynamic_route', 'user'];
/**
* {@inheritdoc}
......@@ -26,6 +26,7 @@ class MenuLinkContentDeriverTest extends KernelTestBase {
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('menu_link_content');
}
......
......@@ -310,4 +310,114 @@ public function testModuleUninstalledMenuLinks() {
$this->assertEqual(count($menu_links), 0);
}
/**
* Tests handling of pending revisions.
*
* @coversDefaultClass \Drupal\menu_link_content\Plugin\Validation\Constraint\MenuTreeHierarchyConstraintValidator
*/
public function testPendingRevisions() {
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('menu_link_content');
// Add new menu items in a hierarchy.
$default_root_1_title = $this->randomMachineName(8);
$root_1 = $storage->create([
'title' => $default_root_1_title,
'link' => [['uri' => 'internal:/#root_1']],
'menu_name' => 'menu_test',
]);
$root_1->save();
$default_child1_title = $this->randomMachineName(8);
$child1 = $storage->create([
'title' => $default_child1_title,
'link' => [['uri' => 'internal:/#child1']],
'menu_name' => 'menu_test',
'parent' => 'menu_link_content:' . $root_1->uuid(),
]);
$child1->save();
$default_child2_title = $this->randomMachineName(8);
$child2 = $storage->create([
'title' => $default_child2_title,
'link' => [['uri' => 'internal:/#child2']],
'menu_name' => 'menu_test',
'parent' => 'menu_link_content:' . $child1->uuid(),
]);
$child2->save();
$default_root_2_title = $this->randomMachineName(8);
$root_2 = $storage->create([
'title' => $default_root_2_title,
'link' => [['uri' => 'internal:/#root_2']],
'menu_name' => 'menu_test',
]);
$root_2->save();
// Check that changing the title and the link in a pending revision is
// allowed.
$pending_child1_title = $this->randomMachineName(8);
$child1_pending_revision = $storage->createRevision($child1, FALSE);
$child1_pending_revision->set('title', $pending_child1_title);
$child1_pending_revision->set('link', [['uri' => 'internal:/#test']]);
$violations = $child1_pending_revision->validate();
$this->assertEmpty($violations);
$child1_pending_revision->save();
$storage->resetCache();
$child1_pending_revision = $storage->loadRevision($child1_pending_revision->getRevisionId());
$this->assertFalse($child1_pending_revision->isDefaultRevision());
$this->assertEquals($pending_child1_title, $child1_pending_revision->getTitle());
$this->assertEquals('/#test', $child1_pending_revision->getUrlObject()->toString());
// Check that saving a pending revision does not affect the menu tree.
$menu_tree = \Drupal::menuTree()->load('menu_test', new MenuTreeParameters());
$parent_link = reset($menu_tree);
$this->assertEquals($default_root_1_title, $parent_link->link->getTitle());
$this->assertEquals('/#root_1', $parent_link->link->getUrlObject()->toString());
$child1_link = reset($parent_link->subtree);
$this->assertEquals($default_child1_title, $child1_link->link->getTitle());
$this->assertEquals('/#child1', $child1_link->link->getUrlObject()->toString());
$child2_link = reset($child1_link->subtree);
$this->assertEquals($default_child2_title, $child2_link->link->getTitle());
$this->assertEquals('/#child2', $child2_link->link->getUrlObject()->toString());
// Check that changing the parent in a pending revision is not allowed.
$child2_pending_revision = $storage->createRevision($child2, FALSE);
$child2_pending_revision->set('parent', $child1->id());
$violations = $child2_pending_revision->validate();
$this->assertCount(1, $violations);
$this->assertEquals('You can only change the hierarchy for the <em>published</em> version of this menu link.', $violations[0]->getMessage());
$this->assertEquals('menu_parent', $violations[0]->getPropertyPath());
// Check that changing the weight in a pending revision is not allowed.
$child2_pending_revision = $storage->createRevision($child2, FALSE);
$child2_pending_revision->set('weight', 500);
$violations = $child2_pending_revision->validate();
$this->assertCount(1, $violations);
$this->assertEquals('You can only change the hierarchy for the <em>published</em> version of this menu link.', $violations[0]->getMessage());
$this->assertEquals('weight', $violations[0]->getPropertyPath());
// Check that changing both the parent and the weight in a pending revision
// is not allowed.
$child2_pending_revision = $storage->createRevision($child2, FALSE);
$child2_pending_revision->set('parent', $child1->id());
$child2_pending_revision->set('weight', 500);
$violations = $child2_pending_revision->validate();
$this->assertCount(2, $violations);
$this->assertEquals('You can only change the hierarchy for the <em>published</em> version of this menu link.', $violations[0]->getMessage());
$this->assertEquals('You can only change the hierarchy for the <em>published</em> version of this menu link.', $violations[1]->getMessage());
$this->assertEquals('menu_parent', $violations[0]->getPropertyPath());
$this->assertEquals('weight', $violations[1]->getPropertyPath());
// Check that changing the parent of a term which didn't have a parent
// initially is not allowed in a pending revision.
$root_2_pending_revision = $storage->createRevision($root_2, FALSE);
$root_2_pending_revision->set('parent', $root_1->id());
$violations = $root_2_pending_revision->validate();
$this->assertCount(1, $violations);
$this->assertEquals('You can only change the hierarchy for the <em>published</em> version of this menu link.', $violations[0]->getMessage());
$this->assertEquals('menu_parent', $violations[0]->getPropertyPath());
}
}
......@@ -18,7 +18,7 @@ class PathAliasMenuLinkContentTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['menu_link_content', 'system', 'link', 'test_page_test'];
public static $modules = ['menu_link_content', 'system', 'link', 'test_page_test', 'user'];
/**
* {@inheritdoc}
......@@ -26,6 +26,7 @@ class PathAliasMenuLinkContentTest extends KernelTestBase {
protected function setUp() {
parent::setUp();