Commit 5b9405d6 authored by catch's avatar catch
Browse files

Issue #2856363 by timmillwood, amateescu, plach, pk188, Mile23, catch,...

Issue #2856363 by timmillwood, amateescu, plach, pk188, Mile23, catch, dawehner, yoroy, vijaycs85, Bojhan: Path alias changes for draft revisions immediately leak into live site
parent b7fff873
......@@ -17,7 +17,8 @@
* description = @Translation("An entity field containing a path alias and related data."),
* no_ui = TRUE,
* default_widget = "path",
* list_class = "\Drupal\path\Plugin\Field\FieldType\PathFieldItemList"
* list_class = "\Drupal\path\Plugin\Field\FieldType\PathFieldItemList",
* constraints = {"PathAlias" = {}},
* )
*/
class PathItem extends FieldItemBase {
......
<?php
namespace Drupal\path\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Validation constraint for changing path aliases in forward revisions.
*
* @Constraint(
* id = "PathAlias",
* label = @Translation("Path alias.", context = "Validation"),
* )
*/
class PathAliasConstraint extends Constraint {
public $message = 'You can only change the URL alias for the <em>published</em> version of this content.';
}
<?php
namespace Drupal\path\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 path aliases in forward revisions.
*/
class PathAliasConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
private $entityTypeManager;
/**
* Creates a new PathAliasConstraintValidator 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($value, Constraint $constraint) {
$entity = !empty($value->getParent()) ? $value->getEntity() : NULL;
if ($entity && !$entity->isNew() && !$entity->isDefaultRevision()) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $original */
$original = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
if ($value->alias != $original->path->alias) {
$this->context->addViolation($constraint->message);
}
}
}
}
<?php
namespace Drupal\Tests\path\Functional;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;
/**
* Tests path aliases with Content Moderation.
*
* @group content_moderation
* @group path
*/
class PathContentModerationTest extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['node', 'path', 'content_moderation'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Created a content type.
$node_type = NodeType::create(['name' => 'moderated', 'type' => 'moderated']);
$node_type->save();
// Set the content type as moderated.
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'moderated');
$workflow->save();
$this->drupalLogin($this->rootUser);
}
/**
* Tests node path aliases on a moderated content type.
*/
public function testNodePathAlias() {
// Create some moderated content with a path alias.
$this->drupalGet('node/add/moderated');
$this->assertSession()->fieldValueEquals('path[0][alias]', '');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'moderated content',
'path[0][alias]' => '/moderated-content',
], t('Save and Publish'));
$node = $this->getNodeByTitle('moderated content');
// Add a forward revision with the same alias.
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertSession()->fieldValueEquals('path[0][alias]', '/moderated-content');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'forward revision',
'path[0][alias]' => '/moderated-content',
], t('Save and Create New Draft'));
$this->assertSession()->pageTextNotContains('You can only change the URL alias for the published version of this content.');
// Create some moderated content with no path alias.
$this->drupalGet('node/add/moderated');
$this->assertSession()->fieldValueEquals('path[0][alias]', '');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'moderated content 2',
'path[0][alias]' => '',
], t('Save and Publish'));
$node = $this->getNodeByTitle('moderated content 2');
// Add a forward revision with a new alias.
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertSession()->fieldValueEquals('path[0][alias]', '');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'forward revision',
'path[0][alias]' => '/forward-revision',
], t('Save and Create New Draft'));
$this->assertSession()->pageTextContains('You can only change the URL alias for the published version of this content.');
// Create some moderated content with no path alias.
$this->drupalGet('node/add/moderated');
$this->assertSession()->fieldValueEquals('path[0][alias]', '');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'moderated content 3',
'path[0][alias]' => '',
], t('Save and Publish'));
$node = $this->getNodeByTitle('moderated content 3');
// Add a forward revision with no path alias.
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertSession()->fieldValueEquals('path[0][alias]', '');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'forward revision',
'path[0][alias]' => '',
], t('Save and Create New Draft'));
$this->assertSession()->pageTextNotContains('You can only change the URL alias for the published version of this content.');
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment