diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php index bf0f2cb..6c05e86 100644 --- a/core/modules/taxonomy/src/Entity/Term.php +++ b/core/modules/taxonomy/src/Entity/Term.php @@ -56,7 +56,10 @@ * "edit-form" = "/taxonomy/term/{taxonomy_term}/edit", * "create" = "/taxonomy/term", * }, - * permission_granularity = "bundle" + * permission_granularity = "bundle", + * constraints = { + * "TaxonomyHierarchy" = {} + * } * ) */ class Term extends EditorialContentEntityBase implements TermInterface { @@ -164,7 +167,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDescription(t('The parents of this term.')) ->setSetting('target_type', 'taxonomy_term') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) - ->addConstraint('TaxonomyTermParent') ->setCustomStorage(TRUE); $fields['changed'] = BaseFieldDefinition::create('changed') diff --git a/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraint.php b/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraint.php index d607e70..e09bedd 100644 --- a/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraint.php +++ b/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraint.php @@ -2,18 +2,25 @@ namespace Drupal\taxonomy\Plugin\Validation\Constraint; -use Symfony\Component\Validator\Constraint; +use Drupal\Core\Entity\Plugin\Validation\Constraint\CompositeConstraintBase; /** - * Validation constraint for changing the parent of a term in pending revisions. + * Validation constraint for changing the term hierarchy in pending revisions. * * @Constraint( - * id = "TaxonomyTermParent", - * label = @Translation("Taxonomy term parent.", context = "Validation"), + * id = "TaxonomyHierarchy", + * label = @Translation("Taxonomy hierarchy.", context = "Validation"), * ) */ -class TaxonomyTermParentConstraint extends Constraint { +class TaxonomyHierarchyConstraint extends CompositeConstraintBase { - public $message = 'You can only change the parent for the published version of this term.'; + public $message = 'You can only change the taxonomy hierarchy for the published version of this term.'; + + /** + * {@inheritdoc} + */ + public function coversFields() { + return ['parent', 'weight']; + } } diff --git a/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraintValidator.php b/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraintValidator.php index 86ddf9c..2059a66 100644 --- a/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraintValidator.php +++ b/core/modules/taxonomy/src/Plugin/Validation/Constraint/TaxonomyHierarchyConstraintValidator.php @@ -11,7 +11,7 @@ /** * Constraint validator for changing term parents in pending revisions. */ -class TaxonomyTermParentConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface { +class TaxonomyHierarchyConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface { /** * The entity type manager. @@ -21,7 +21,7 @@ class TaxonomyTermParentConstraintValidator extends ConstraintValidator implemen private $entityTypeManager; /** - * Creates a new TaxonomyTermParentConstraintValidator instance. + * Creates a new TaxonomyHierarchyConstraintValidator instance. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. @@ -42,14 +42,25 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} */ - public function validate($value, Constraint $constraint) { - $entity = !empty($value->getParent()) ? $value->getEntity() : NULL; - + public function validate($entity, Constraint $constraint) { if ($entity && !$entity->isNew() && !$entity->isDefaultRevision()) { - $new_parents = array_column($value->getValue(), 'target_id'); - $original_parents = array_keys($this->entityTypeManager->getStorage('taxonomy_term')->loadParents($entity->id())); + /** @var \Drupal\taxonomy\TermStorageInterface $term_storage */ + $term_storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId()); + + $new_parents = array_column($entity->parent->getValue(), 'target_id'); + $original_parents = array_keys($term_storage->loadParents($entity->id())); if ($new_parents != $original_parents) { - $this->context->addViolation($constraint->message); + $this->context->buildViolation($constraint->message) + ->atPath('parent') + ->addViolation(); + } + + /** @var \Drupal\Core\Entity\ContentEntityInterface $original */ + $original = $term_storage->loadUnchanged($entity->id()); + if (!$entity->weight->equals($original->weight)) { + $this->context->buildViolation($constraint->message) + ->atPath('weight') + ->addViolation(); } } } diff --git a/core/modules/taxonomy/src/TermForm.php b/core/modules/taxonomy/src/TermForm.php index 4667dd7..7b6c7c9 100644 --- a/core/modules/taxonomy/src/TermForm.php +++ b/core/modules/taxonomy/src/TermForm.php @@ -120,7 +120,7 @@ public function buildEntity(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ protected function getEditedFieldNames(FormStateInterface $form_state) { - return array_merge(['parent'], parent::getEditedFieldNames($form_state)); + return array_merge(['parent', 'weight'], parent::getEditedFieldNames($form_state)); } /** @@ -131,6 +131,9 @@ protected function flagViolations(EntityConstraintViolationListInterface $violat foreach ($violations->getByField('parent') as $violation) { $form_state->setErrorByName('parent', $violation->getMessage()); } + foreach ($violations->getByField('weight') as $violation) { + $form_state->setErrorByName('weight', $violation->getMessage()); + } parent::flagViolations($violations, $form, $form_state); } diff --git a/core/modules/taxonomy/tests/src/Functional/TaxonomyTermContentModerationTest.php b/core/modules/taxonomy/tests/src/Functional/TaxonomyTermContentModerationTest.php index d7c9664..3aa3051 100644 --- a/core/modules/taxonomy/tests/src/Functional/TaxonomyTermContentModerationTest.php +++ b/core/modules/taxonomy/tests/src/Functional/TaxonomyTermContentModerationTest.php @@ -58,7 +58,7 @@ public function testTaxonomyTermParents() { $child = $this->createTerm($this->vocabulary, ['langcode' => 'en', 'moderation_state' => 'published', 'parent' => $parent_1->id()]); $taxonomy_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); - $validation_message = 'You can only change the parent for the published version of this term.'; + $validation_message = 'You can only change the taxonomy hierarchy for the published version of this term.'; // Add a pending revision without changing the term parent. $this->drupalGet('taxonomy/term/' . $child->id() . '/edit'); @@ -120,6 +120,15 @@ public function testTaxonomyTermParents() { $this->assertSession()->pageTextNotContains($validation_message); $taxonomy_storage->resetCache(); $this->assertEquals([$parent_2->id()], array_keys($taxonomy_storage->loadParents($child->id()))); + + // Add a pending revision and change the weight. + $this->drupalGet('taxonomy/term/' . $child->id() . '/edit'); + $this->drupalPostForm(NULL, [ + 'weight' => 10, + ], 'Save and Create New Draft'); + + // Check that weight was not changed. + $this->assertSession()->pageTextContains($validation_message); } }