Problem/Motivation
Content Moderation sets the 'default revision' flag in \Drupal\content_moderation\Entity\Handler\ModerationHandler::onPresave()
based on various logic checks in \Drupal\content_moderation\EntityOperations::entityPresave()
, which prevents an entity validation restriction to be applied to an entity form.
For a concrete example: in #2858431: Book storage and UI is not revision aware, changes to drafts leak into live site we shouldn't allow users to submit the node form if they made any changes to the book outline and the new revision which results from that node form submission will not be a default revision. We should be able to simply throw an entity validation error and not allow the form to be submitted until either 1) the book changes are reverted or 2) the node will be made the default revision.
Proposed resolution
Move the logic from \Drupal\content_moderation\Entity\Handler\ModerationHandler::onPresave()
and \Drupal\content_moderation\EntityOperations::entityPresave()
somewhere in the entity form processing.
Remaining tasks
Do it.
User interface changes
Nope.
API changes
Not sure yet.
Data model changes
Nope.
Comment | File | Size | Author |
---|---|---|---|
#20 | 2883868-followup.patch | 1.74 KB | amateescu |
#15 | interdiff.txt | 3.34 KB | amateescu |
#15 | 2883868-15.patch | 9.08 KB | amateescu |
#13 | interdiff.txt | 712 bytes | amateescu |
#13 | 2883868-13.patch | 9.53 KB | amateescu |
Comments
Comment #2
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedI think our best bet is to move the logic from
\Drupal\content_moderation\Entity\Handler\ModerationHandler::onPresave()
and\Drupal\content_moderation\EntityOperations::entityPresave()
to an entity builder, something like the patch attached.Comment #3
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedHowever, after looking at the code some more, I'm not sure what would happen when some module decides to remove the 'moderation_state_default' widget from the form. We probably need to move all this code to a generic #entity_builder added through
entity_form_alter()
instead.Comment #5
timmillwoodWe would also need to make sure this is done on Entity forms and on forms such as
\Drupal\content_moderation\Form\EntityModerationForm
.This could also cause issues if the moderation state is changed programmatically and not via a form. The main place I can think of that this is done is tests.
Comment #6
Sam152 CreditAttribution: Sam152 commentedYeah, we can't purely rely on forms to do this for us, it has to work at an API level for changes made programmatically as well as for REST support. Given we want the same validation to apply for REST, is there another concept which can accomodate this earlier in the lifecycle?
Comment #7
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented#5 and #6 are correct, we definitely want this to work on the API level, so how about doing it in
\Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList::onChange()
?Comment #9
Sam152 CreditAttribution: Sam152 commentedI wonder if this will also address #2803717: Allow 'syncing' content to be updated in content moderation without forcing the creation of a new revision.
Comment #10
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@Sam152, I don't think so, it's related but not really in the scope of this bug.
Since #7 failed as well (and rightfully so), it seems that the only thing we can do is duplicate the logic in
preSave()
and use it inonChange()
too. I'm still pondering if this covers the case for forms as well, since they don't change the moderation_state value directly.No interdiff because it's mostly a new patch.
Comment #13
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedWe just need to update the expected exception now that
\Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList::onChange()
calls\Drupal\workflows\WorkflowInterface::getState()
, which throws an\InvalidArgumentException
if the given state doesn't exist.Comment #15
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedOk, after looking at the tests in
EntityStateChangeValidationTest
it seems that we shouldn't throw an error when changing the moderation state to an invalid one, that's being handled in the entity validation process. So we should simply check if the new state is valid for the given workflow before changing the host entity's 'default revision' flag and publishing status.Comment #16
plachLooks good and works well, tested in my local env.
It would be great to get this in ASAP to unblock the following issues:
Comment #17
catchCommitted/pushed to 8.4.x, thanks!
Comment #19
tstoecklerKnocking back to get some clarification on the first point, although it would be nice to quickly fix 2./3. as well, but they are really minor, so feel free to knock back to RTBC otherwise.
Do we still need this given that
ModerationStateFieldItemList::onChange()
seems to to the same thing? At the very least it seems the$entity->isDefaultRevision()
call can be removed fromModerationHandler
? #7 / #10 seem to reference this, but it's not entirely clear to me what's going on.As far as I can tell
$this->entityTypeManager
is already available in this class.I get that the current workflow state field will always have only a single item, but since we are being passed
$delta
anyway, I think it would make sense to use it here, instead of hardcoding 0.Edit: X-posted with the commit. Thus, leaving at fixed, but would still like to get some clarification on point 1.
Comment #20
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRe #19.1:
Yep, we still need to do the same thing in
preSave()
becauseModerationStateFieldItemList::onChange()
does not handle the case when an entity is created with an upfront value for moderation_state.ModerationStateFieldItemList::onChange()
is called by\Drupal\Core\Field\FieldItem(List)Base::set()
(actually, by\Drupal\Core\TypedData\Plugin\DataType\Map::set()
), which doesn't happen on entity creation.Here's a small followup patch for points 2. and 3. :)
Comment #21
plachAnd RTBC again, thanks @tstoeckler for spotting these!
Comment #22
tstoecklerAhh, that kind of (?) makes sense, as I guess nothing is "changing" in that case. Very interesting, in any case, hadn't thought of that. That definitely makes things clear, thanks!
And thanks for the quick follow-up!
Comment #23
plachOpened a proper follow-up for this at #2897483: Use injected entity type manager in ModerationInformation, moving back to fixed.
Comment #24
plachComment #26
eyilmazAre we not missing a $entity->setNewRevision(TRUE); here?