Problem/Motivation

This is a bit of a complex bug I'm encountering. It involves 3 core modules and optionally 1 contrib (pathauto), but I think content moderation may be at the heart of it because I can't seem to reproduce it with non-moderated entities.

The problem is that a translation of an entity cannot be saved if the path alias differs from the published original language version.

To reproduce:

1) Create a node type.
2) Add a moderation workflow to it.
3) Add another language to your site.
4) Enable content translations on that node.
5) Add a pathauto pattern to the node that contains the title.
6) Create an English version of the node.
7) Publish the node through the workflow.
8) Add a translation of that node. Change the title.
9) Save the node (as a draft or other unpublished state - I'm not sure why you can save it once but not a second time).
10) Edit the node again and try to save again (as a draft or other unpublished state).

Form error: "You can only change the URL alias for the published version of this content."

My initial thought was that Pathauto was to blame but after looking in PathAliasConstraintValidator.php I feel like there needs to be some additional logic for translations, moderation, etc. I think (not know) that Pathauto is just exposing this issue because it's changing the alias.

Proposed resolution

TODO

Remaining tasks

Investigate further.

Comments

mstef created an issue. See original summary.

timmillwood’s picture

Issue tags: +Needs tests

This is because if you change the title, pathauto will change the path alias. Path aliases are not revisionable therefore cannot be changed in an unpublished revision when there's already a published revision.

Rather than just closing with a "works as designed" comment I thought it'd be best if we add a test to this issue to show the issue. I think the translations brings an interesting element which I don't think is currently tested in core.

mstef’s picture

Thanks for the explanation. So then this is most likely an issue with Pathauto?

mstef’s picture

Title: Unable to publish a translation if the path alias changes » Unable to save a translation if the path alias changes
Issue summary: View changes
mstef’s picture

You know way more than I do about this, but I'm still thinking this may be a core issue. When the error is thrown Pathauto's PathautoGenerator::updateEntityAlias() is not even called yet. It only is when the first draft of the translation is created -- which works. There is no error on the first save and the path is created and saved. It's the second save where the error is thrown.

mstef’s picture

PathAliasConstraintValidator::validate() is loading the "original" node via:

$original = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());

but it's never translated.

In my scenario, looking at $original, it's the English version whereas the French version is being saved.

mstef’s picture

This is sloppy but this does seem to resolve it:

if ($original->language()->getId() != $entity->language()->getid()) {
  $original = $original->getTranslation($entity->language()->getId());
}
sylus’s picture

As the fix is related to pathauto should I create a patch for that over in other issue? Ran into this issue as well but the suggestion did fix problem for me.

Nevermind didn't realize was actually patching the path module, patch forthcoming.

sylus’s picture

sylus’s picture

Status: Active » Needs review
mathiasgmeiner’s picture

The patch from #9 is working fine, thanks!

timmillwood’s picture

Component: content_moderation.module » path.module

@sylus nice find! I guess this still needs tests though ;)

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

gábor hojtsy’s picture

+++ b/core/modules/path/src/Plugin/Validation/Constraint/PathAliasConstraintValidator.php
@@ -48,6 +48,9 @@ public function validate($value, Constraint $constraint) {
       $original = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
+      if ($original->language()->getId() != $entity->language()->getid()) {
+        $original = $original->getTranslation($entity->language()->getId());
+      }

Hm, are there any other places where this kind of logic would appear?

Also getTranslation() may throw an \InvalidArgumentException if the translation did not exist, is that not the case if a new translation is just being added and not yet in storage?

kcolaers’s picture

StatusFileSize
new1.08 KB

Also getTranslation() may throw an \InvalidArgumentException if the translation did not exist, is that not the case if a new translation is just being added and not yet in storage?

An \InvalidArgumentException is indeed thrown in some cases. We could reproduce this by adding a translation (but not yet saving it) for a node with an entity reference, then removing the reference in this translation.

Attached patch to check if the translation exists.

matoeil’s picture

Hi there,

the same form error happens using path module.
Tell me if i am wrong, It means to me it is not possible to have a drupal multilingual site with moderation activated and url rewriting.

EDIT: my previous comment should be reconsidered as i cannot reproduce the problem anymore.
so far so good

porchlight’s picture

I was running into the issue brought up by comment #14 where the translation had not been created yet, so it was never getting inside the if statement, and never getting the translation, but also when trying to save my translated draft the url alias field was empty, while the english field was not, so checking the $value->alias again the $original->path->alias was always return the constraint validation since it was empty compared to the english alias. This sloppy code seems to get around that.

binyc01’s picture

After applying patch from #15, I ran into a similar issue as #17. I can save the first draft of a translated content, but get the validation error when saving the same draft a second time.

So in addition to the #15 patch, I added a check for an empty alias:

if (!empty($value->alias) && $value->alias != $original->path->alias) {
  $this->context->addViolation($constraint->message);
}
binyc01’s picture

StatusFileSize
new1.19 KB

Added empty alias check to #15 patch.

yang_yi_cn’s picture

Status: Needs review » Needs work

I looked at the code logic in #17 and #19 and I think they are both sloppy.

The logic should be:
- English and French translations should be able to have different path.
- When editing new revision of the content in the same language, you cannot change path alias in draft mode, unless you publish it, then you can change path.

I think the pseudo logic should be like this:


if ($entity && !$entity->isDefaultRevision()) {
  $original = Unchanged;
  $is_translation = $original->language()->getId() != $entity->language()->getid();
  $existing_translation = getTranslation
  $is_new = $entity->isNew() || ($is_translation && empty($existing_translation));
  if (!$is_new) {
     // At this point $existing_translation won't be empty.
     $previous_revision = $is_translation ? $existing_translation : $original;
     if ($value->alias != $previous_revision->path->alias) {
       $this->context->addViolation($constraint->message);
     }
  }
}
porchlight’s picture

Confirmed my patch in #17 does NOT work. It allows me to save the node, but it seems to unpublish the original language.

porchlight’s picture

Never mind... it does work, but I like #19 better.

timmillwood’s picture

We're still waiting on tests.

sylvain lavielle’s picture

#19 patch fixed the problem for me !
Thanks

anish.a’s picture

It doesn't fix the problem.

Installed relevant modules - pathauto

My test case is as below.

  • Create a workflow with draft -> approved -> published workflow.
  • Create a node in English, mark as published, create a URL alias.
  • Create a translation (in my case Chinese), with different URL alias and mark as published.
  • Change the translation to draft, with URL alias changed.

It shows "You can only change the URL alias for the published version of this content."

I applied patch #19

olivier.br’s picture

#19 solved the issue for me on 8.6.x-dev with content moderation and pathauto.

I was unable to save a new draft revision of a published translation of a node.
Even without changing the path alias.

andreyjan’s picture

#1 works for me when the latest version of pathauto module is installed.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

huzooka’s picture

Status: Needs work » Needs review
StatusFileSize
new5.52 KB

Test-only patch added.

Status: Needs review » Needs work
huzooka’s picture

Status: Needs work » Needs review
StatusFileSize
new6.6 KB

Complete test, mainly based on #19.

huzooka’s picture

Hiding my patches since I was fixing an another issue and restoring the previous status :)

Based on the issue's title and summary, this is a 'works like designed' issue or a feature request.

Since path aliases don't have status (right now), if core would allow to change the path alias when creating a new draft, then it would be published immediately

What I fixed: #3001124: Unable to create new draft for content translation even if the path alias does not change

berdir’s picture

Commented on the other issue first, but after seeing this, I don't think we need to split this.

Yes, this issue title is unspecific but we can improve that, the issue summary shows that it is about the second save, just like your issue. This one also involves pathauto, which does cause a slightly different problem, but if we do the fix that I proposed over there (only compare the alias if we have a matching translation), then I believe it would also kinda work with pathauto even though we could still improve it.

vurt’s picture

StatusFileSize
new1004 bytes

I still had the issue with the current core 8.6.4.

I rerolled the patch from #19 to work with this version.

berdir’s picture

Status: Needs review » Postponed (maintainer needs more info)

I don't see how that could fix anything, the code below already checks for having a translation and goes further than this patch used to, by not validating at all if a new translation is added.

Please provide steps to reproduce if you still have a problem and what exactly you expect to happen.

With the other issue being fixed, this is IMHO a duplicate now.

vurt’s picture

You're right Berdir: After clearing caches saving worked without the patch.

Sorry for the confusion && thanks

berdir’s picture

Status: Postponed (maintainer needs more info) » Closed (duplicate)

Thanks for reporting back, I'm closing this as a duplicate then. I think there shouldn't have been two issues initially.