Problem/Motivation

The ContentModerationState entity type is @internal so any time users interact with it directly, they are risking API breaks. One of the convenient touch points with the entity is implementing hook_entity_(insert|update) as seen in the content_moderation_notifications. Implementing these hooks gives you a single place to react to content states changes.

Proposed resolution

Provide an alternative to these hooks so users have a consistent and @api way to react to any item of content having its state changed. An event suits this purpose nicely.

Remaining tasks

#39 = https://www.drupal.org/project/drupal/issues/2873287#comment-12304979
Change record.

Review and commit.

User interface changes

None.

API changes

An additional event.

Data model changes

CommentFileSizeAuthor
#79 2873287-content-moderation-events-79.patch20.15 KBBerdir
#76 2873287-content-moderation-events-76.patch20.1 KBpenyaskito
#76 2873287-content-moderation-events.interdiff.74-76.txt18.07 KBpenyaskito
#75 2873287-content-moderation-events-74.patch19.47 KBpenyaskito
#75 2873287-content-moderation-events.interdiff.72-74.txt11.9 KBpenyaskito
#73 2873287-content-moderation-events-72.patch15.65 KBpenyaskito
#72 2873287-content-moderation-events.interdiff.70-72.patch4.09 KBpenyaskito
#70 2873287-70.patch15.54 KBBerdir
#70 2873287-70-interdiff.txt819 bytesBerdir
#68 interdiff_67-68.txt882 bytespradhumanjain2311
#68 2873287-68.patch15.54 KBpradhumanjain2311
#67 interdiff-2873287-66_67.txt1.35 KBAnchal_gupta
#67 2873287-67.patch15.54 KBAnchal_gupta
#66 interdiff_65-66.txt3.24 KBpooja saraah
#66 2873287-66.patch15.54 KBpooja saraah
#65 2873287-65.patch15.57 KBBerdir
#65 2873287-65-interdiff.txt649 bytesBerdir
#50 2873287-50.patch15.5 KBManuel Garcia
#50 interdiff-2873287-48-50.txt1.17 KBManuel Garcia
#48 2873287-48.patch15.42 KBmarcoscano
#45 2873287-45.patch15.41 KBSam152
#33 2873287-33.patch15.41 KBtimmillwood
#24 2873287-24.patch15.44 KBSam152
#24 interdiff.txt1.6 KBSam152
#13 2873287-13.patch15.44 KBSam152
#13 interdiff.txt2.94 KBSam152
#10 2873287-10.patch12.49 KBSam152
#10 interdiff.txt20.13 KBSam152
#5 2873287-05.patch8.45 KBjhedstrom
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Sam152 created an issue. See original summary.

timmillwood’s picture

As I mentioned in IRC we used to have events that fired when a moderation state was changed, this is how Workbench Moderation does it, but when we moved to store the state in a ContentModerationState entity we decided that the event wasn't needed because we have the create, update, and insert hooks. Although if we're not supposed to interface directly with ContentModerationState entities maybe we should add the events back in?

Sam152’s picture

Yeah, if it's marked as internal, we don't want to expose that entity to developers if it can be helped. Implementing an update hook and using the fields for the @internal entity wouldn't be a stable API.

jhedstrom’s picture

Assigned: Unassigned » jhedstrom
jhedstrom’s picture

Assigned: jhedstrom » Unassigned
Status: Active » Needs review
FileSize
8.45 KB

This adds and fires create and update events.

Sam152’s picture

Status: Needs review » Needs work

Looking good, some feedback.

  1. +++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php
    @@ -176,7 +177,15 @@ public function save() {
    +    $event = new ContentModerationStateEvent($this);
    

    The point of the issue was that users wouldn't ever interact or know about the entity. Instead of passing this into the event, we should pull out what is relevant and put into the event. That can safely keep the entity type @internal while providing @api :)

  2. +++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php
    @@ -176,7 +177,15 @@ public function save() {
    +      \Drupal::service('event_dispatcher')->dispatch(ContentModerationStateEvent::CREATED, $event);
    ...
    +      \Drupal::service('event_dispatcher')->dispatch(ContentModerationStateEvent::UPDATED, $event);
    

    Can cache the event dispatcher.

  3. +++ b/core/modules/content_moderation/src/Event/ContentModerationState.php
    @@ -0,0 +1,60 @@
    +  /**
    +   * Name of the event fired when saving a new moderation state entity.
    +   *
    +   * @Event
    +   *
    +   * @var string
    +   */
    +  const CREATED = 'content_moderation.created';
    ...
    +  /**
    +   * Name of the event fired when updating an existing moderation state entity.
    +   *
    +   * @Event
    +   *
    +   * @var string
    +   */
    +  const UPDATED = 'content_moderation.updated';
    

    We should remove all entity-centric things that allude to the ContentModerationState entity from the event. Maybe this should be one event, but with a method to get the entity whose state has changed, so developers can check isNew()?

  4. +++ b/core/modules/content_moderation/tests/src/Kernel/Event/ContentModerationStateTest.php
    @@ -0,0 +1,53 @@
    +  /**
    +   * Tests events for adding and updating moderation state entities.
    +   */
    +  public function testCreateUpdateStates() {
    +    // Utilize the state system to track if the event was fired.
    +    $this->assertFalse(\Drupal::state()->get('content_moderation_test_event.created', FALSE));
    +    $state = ContentModerationState::create(['workflow' => 'editorial']);
    +    ContentModerationState::updateOrCreateFromEntity($state);
    +    // @see \Drupal\content_moderation_test_event\EventSubscriber\Test::onCreate
    +    $this->assertEquals($state->id(), \Drupal::state()->get('content_moderation_test_event.created', FALSE));
    

    I wonder if we can mock event dispatcher and put it into the container and assert the dispatch methods are called instead?

    Looks like symfony does something similar in \Symfony\Component\HttpKernel\Tests\Fragment\InlineFragmentRendererTest::testRenderExceptionIgnoreErrors, but I couldn't find an example in core.

jhedstrom’s picture

Issue tags: +Workflow Initiative

The point of the issue was that users wouldn't ever interact or know about the entity. Instead of passing this into the event, we should pull out what is relevant and put into the event. That can safely keep the entity type @internal while providing @api :)

Ah, good call. So perhaps the event can have something along these lines for methods:

  • getModeratedEntity
  • getWorkflow
  • getNewState
  • getOldState

(Those last 2 methods I haven't thought through if we have that information or not...I assume we do.)

jhedstrom’s picture

I wonder if we can mock event dispatcher and put it into the container and assert the dispatch methods are called instead?

We could potentially do that, but calling the actual event listener seems valuable too, since, in this case, we can verify the event listener had access to the moderation state entity (when refactored, we could verify access to the moderated entity, the workflow, the transition, etc).

Sam152’s picture

#7 sounds good to me.

Sam152’s picture

Status: Needs work » Needs review
FileSize
20.13 KB
12.49 KB

Moving this along a bit. Right now it's red based on another bug I'll open as a blocker. Getting the original state was surprisingly annoying, but seemed to work.

I was able to test the event by replacing the dispatcher in the container, seemed to work pretty well.

Sam152’s picture

Status: Needs review » Needs work

The last submitted patch, 10: 2873287-10.patch, failed testing.

Sam152’s picture

Status: Needs work » Needs review
FileSize
2.94 KB
15.44 KB

This is still blocked, but fixing the fail introduced by the changes. Now that we fire an event which loads some extra information for the event, we can't just create phony ContentModerationState entities for the storage test.

Status: Needs review » Needs work

The last submitted patch, 13: 2873287-13.patch, failed testing. View results

timmillwood’s picture

timmillwood’s picture

Title: Dispatch events for changing content moderation states » [PP-1] Dispatch events for changing content moderation states
Status: Needs work » Postponed
Related issues: +#2881645: ContentModerationState 'workflow' column empty for all non-default translations.
bojanz’s picture

1) Can't we throw the event on the workflows module level?

Otherwise people using workflows without content_moderation will once again have the same need, and an issue will eventually get raised duplicating this work.

2) Would be great to have pre_transition and post_transition events, instead of a single changed event (the equivalent of post_transition).

Sam152’s picture

This particular issue is designed to specifically replace the use case of implementing hook_content_moderation_state_(insert|update). This is important, because we're trying to reduce all touch points with the content_moderation_state entity, given it's marked @internal and therefore could be an implementation detail that changes down the track. It's acknowledging that an api exists to accomplish something, but given it's a bad idea to depend on something @internal which could go away, have something better in its place.

The event and hook importantly contain the entity being moderated. I don't it makes sense for that particular information to be in a generic workflows event and I'm not sure how we'd go about making something generic that would accomodate this use case.

bojanz’s picture

@Sam152
I literally have the same event in state_machine: https://github.com/bojanz/state_machine/blob/8.x-1.x/src/Event/WorkflowT...
As you can see, it's almost the same, just some wording differences.
So, definitely generic enough.

(And the reason why I'm saying this is because I'd love to see workflows in core achieve feature parity with state_machine at some point, so that I can deprecate state_machine. The event is half of that).

tacituseu’s picture

Since Workflow is just a ConfigEntity now and the storage isn't handled in generic way (each WorkflowType implementation is responsible for it), it would be tricky/hacky to get $entity as context in the event,

Content Moderation uses bolted on ContentEntity for storage, having plenty of issues trying to keep it in sync with translations and revisions of the moderated entity (also views integration), this feels like a lot of effort just to duplicate what @FieldType would get out of the box.

Sam152’s picture

#20 is spot on, there currently no solution which provides generic field/entity based storage of a state, with appropriate transitions wrapped around them, so there really isn't any generic context on how to fire an event when a workflow is being used.

If core workflows provides the mechanism for configuring states and transitions, the type plugins serve to integrate that configuration into whatever storage or feature can use them. In the case of content_moderation, it's an entity type, but as explored in #2835545: Provide a Workflow FieldType that references a workflow entity and tracks the current state of an entity, field types could easily satisfy other use cases. I think a @Fieldtype and @WorkflowType together would serve the use case state_machine current provides.

For that reason, it's up to the module implementing the plugin to provide context and events around how the workflow is being leveraged.

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

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

timmillwood’s picture

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

Moving this back to 8.4.x, this is a "should have" Content Moderation issue and blocking it becoming stable in 8.4.0

Sam152’s picture

Status: Postponed » Needs review
FileSize
1.6 KB
15.44 KB

Rerolling with some minor changes the the function name for consistency. Back to active again now that the blocker is resolved.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community
Sam152’s picture

Issue summary: View changes
Sam152’s picture

Issue summary: View changes
Sam152’s picture

Issue summary: View changes
Sam152’s picture

Issue summary: View changes
Sam152’s picture

Issue summary: View changes
Sam152’s picture

Title: [PP-1] Dispatch events for changing content moderation states » Dispatch events for changing content moderation states

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 24: 2873287-24.patch, failed testing. View results

timmillwood’s picture

jhedstrom’s picture

Since this patch adds the official way to react to moderation state changes, it would be really good to get into the first stable version of content moderation (eg, 8.4.0), so that contrib can do things the correct way, and not have to refactor for 8.5.

Content moderation notifications is one such example.

amateescu’s picture

The patch looks great to me, I just have one question:

--- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateStorageSchemaTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateStorageSchemaTest.php

I'm very curious why this test needed to be changed because I don't see how these changes could affect the rest of the patch.

And another question for @bojanz: do you think that #20 and #21 address your concern properly?

Sam152’s picture

+++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateStorageSchemaTest.php
@@ -88,18 +97,22 @@ public function testUniqueKeys() {
-    $this->assertStorageException([
-      'content_entity_type_id' => 'entity_test',
-      'content_entity_id' => $node->id(),
-      'content_entity_revision_id' => $node->getRevisionId(),
-    ], FALSE);
+    $block_content = BlockContent::create([
+      'info' => 'Test block',
+      'type' => 'example',
+      'moderation_state' => 'draft',
+    ]);
...
-    $this->assertStorageException([
-      'content_entity_type_id' => $node->getEntityTypeId(),
-      'content_entity_id' => 9999,
-      'content_entity_revision_id' => 9999,
-    ], FALSE);
+    $second_node = Node::create([
+      'title' => 'Test title',
+      'type' => 'example',
+      'moderation_state' => 'draft',
+    ]);

Both these test cases were creating a ContentModerationState entity that didn't correspond to a real entity that had moderation enabled. It wasn't enabled for entity_test and node 9999 doesn't exist.

Now that we're dispatching an event with the moderated entity, it needs to be a real entity. So in the test case, we're creating real moderated entities that cover the same circumstances.

jhedstrom’s picture

This missed 8.4.0, but I'd still like to advocate for it getting into 8.4. Otherwise contrib modules will start to leverage entity events on the moderation state entity that we are trying to keep internal here, and then need to be re-written for 8.5, which will be difficult to maintain BC for both versions at that point.

Sam152’s picture

Category: Feature request » Bug report
Issue tags: +Needs change record

Do we allow new features in beta experimental modules in patch releases? I do agree though, without a supported alternative, implementing the hook will cause some pain in the future.

Now that we're beta, perhaps this could do with a change record, which would also serve to make people aware this exists.

xjm’s picture

Version: 8.4.x-dev » 8.5.x-dev
Category: Bug report » Task
Status: Reviewed & tested by the community » Needs review

Alright, I discussed this issue with @timmillwood and @Sam152 this morning, and based on that discussion I came to some decisions about this issue:

  1. This isn't a bug, so recategorizing to task.
     
  2. As an API addition to a beta module, it's minor-only, so moving to 8.5.x.
     
  3. I don't think we can really claim that hooks provided by the entity API are internal, even if there's an @internal on the entity type itself. A developer implementing the hooks wouldn't have a very direct way of knowing, so if we truly considered them internal we'd have to raise that to the developer some way more explicitly, or even prevent them from being implemented somehow. @Sam152 said he'd like to explore this. However, I think that by their very nature hooks are API, so I don't think it's even good DX to try to make them internal.
     
  4. I think having both the event and the hooks is bad DX and redundant. It should be one or the other.
     
  5. We do need to provide full BC and upgrade paths for the module now that it's in beta. I think we might even need to do so for the entity type despite it being marked as internal -- it'd be disruptive. And anyway, this issue isn't about removing or changing the moderation state entity type (and an issue for that doesn't even exist yet). If we do go the route of deprecating (for removal in D9) the entity in the future, we could reopen this issue, but I don't think we should add the event based on some future direction we haven't even explored yet.
     
  6. @timmillwood said that he thought that we should not be using hooks and that the direction for D9/D10 should be to replace hooks with events, but we haven't made such a policy yet. @catch also raised that he's strongly opposed to replacing the hook system with events as they are. Quoting @catch:

    I’m completely opposed to using event dispatcher everywhere, the DX is bad.
    You have to have an Event class for everything, even when there’s no information to pass around.
    Also the way we use Event::CONSTANT now is more fragile than the hook system.
    Event dispatcher also only has priority, there’s no before/after which hook_module_implements_alter(), ugly as it is, provides.
    So it’s just not an adequate replacement, and it wouldn’t be an improvement except for it being OOP.
    We could do #2237831: Allow module services to specify hooks
    Then invoke a hook everywhere we currently invoke an event (including adapters for events that symfony provides), and deprecate all the events.

    I'm less sure about that, and it's not in scope here, but it's therefore also not in scope to decide events are preferable without that having been adopted core-wide already. We shouldn't make decisions based on a policy/best practice we haven't agreed to adopt. (Put otherwise, #1972304: Add a HookEvent and #1509164: Use Symfony EventDispatcher for hook system do not have consensus, so we should not make decisions as if they do, and we should not add events in a fragmented way so that it's a mixture of hooks and events and you can't know whether to expect one or the other except based on the subsystem maintainers' or patch authors' preferences).

So, TLDR, let's stick with the hooks for now. I recommend either postponing this issue on an issue to deprecate the moderation state entity and its hooks, or probably wontfixing it entirely. Setting NR for now in the absence of those issues and to give others a chance to review this.

Thanks everyone! Sorry for the delay; it took me some time to get to the bottom of what the issues were surrounding this.

Edit: Adding whitespace for readability.

Sam152’s picture

The ship may have sailed for the ContentModerationState entity, but I've opened #2917276: Allow entity types to be @internal in such a way that removing them doesn't violate any BC to see if it'd even be possible for some future entity type.

Re: the implementation of an event in this issue, I suppose my understanding was also aligned with 6. The movement as I've seen it has been towards implementing events, tagged services and plugins (other stuff too?) where appropriate instead of firing hooks. These concepts individually might not cover all of the semantics of hooks, but if the shoe fits, I think it's hugely preferable to choose one of these patterns. I'd rather think about it as creating APIs with the tools we have (whatever those are) instead of replacing hooks 1-for-1 with some other single concept. If what we have is unsatisfactory for a particular use case, what design pattern can address that?

I did think in this case an event was perfectly suited. The semantics are such that order isn't really important, the data is flowing in one direction and the encapsulation of the data in the event object is nice to work with, type hinted etc.

We have #2551893: Add events for matching entity hooks which is kind of related, but the idea behind this particular issue was "forget about specific entity types, what happens when any content changes state" and also a way to decouple that entirely from the @internal entity type.

jhedstrom’s picture

I think we still either need something like the event proposed here, or to make the ContentModerationState not internal only. The content moderation notifications module has to do some acrobatics to get the previous state of a moderated entity during node save, whereas with this event, that would be much more straight-forward. Alternatively, if the content moderation state entity implemented a public interface for read-only operations (eg, the moderation state has changed from x to y, etc), that would work as well.

samuel.mortenson’s picture

I'm working on adding Content Moderation support to Workbench Email in #2931097: Support the core Content Moderation module and they rely on the existing events to know when a state has changed.

hass’s picture

Patch is still green and was already rtbc.

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

Sam152’s picture

Rerolling this. I think even if there is no policy to replace all hooks with events, I think in this case it does make sense. I think @jhedstrom nailed it in #41, to get the equivalent information from a hook (which the ContentModerationState entity internally already mostly understands and has loaded), acrobatics are required. Pulling out the relevant code into the hooks, the DX looks something like:

function hook_content_moderation_state_insert($entity) {
  moderation_state_was_changed($entity);
}

function hook_content_moderation_state_update($entity) {
  moderation_state_was_changed($entity);
}

/**
 * Respond to changes in moderation states.
 *
 * A function that contains:
 *   - $moderated_entity
 *   - $original_state
 *   - $new_state
 *   - $workflow
 */
function moderation_state_was_changed($entity) {
  $moderated_entity = \Drupal::entityTypeManager()
    ->getStorage($entity->content_entity_type_id->value)
    ->loadRevision($entity->content_entity_revision_id->value);
  if ($moderated_entity instanceof TranslatableInterface) {
    $moderated_entity = $moderated_entity->getTranslation($entity->activeLangcode);
  }

  if (!$entity->getLoadedRevisionId()) {
    $original_state = FALSE;
  }
  else {
    $original_content_moderation_state = \Drupal::entityTypeManager()
      ->getStorage($entity->getEntityTypeId())
      ->loadRevision($entity->getLoadedRevisionId());
    if (!$entity->isDefaultTranslation() && $original_content_moderation_state->hasTranslation($entity->activeLangcode)) {
      $original_content_moderation_state = $original_content_moderation_state->getTranslation($entity->activeLangcode);
    }
    $original_state = $original_content_moderation_state->moderation_state->value;
  }
  $new_state = $entity->moderation_state->value;
  $workflow = $entity->workflow->target_id;
}
Nigel Cunningham’s picture

Is there discussion somewhere regarding why the entity is considered internal?

I have a client wanting transitions to be able to require comments on the reason for the transition; it sounds to me like having a fieldable transition entity is exactly what I'd be after.

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

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

marcoscano’s picture

+1 for this, it will be really useful, especially for people struggling with the $entity->original weirdness. #2914901: content moderation state entity with no original value is an example of a scenario where having this event would make developers lives much easier.

Patch #45 didn't apply cleanly anymore. Attached re-roll.

Status: Needs review » Needs work

The last submitted patch, 48: 2873287-48.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
1.17 KB
15.5 KB

Arrived here from this rules task #2923001: Support new core Workflows events - which is blocked on this.

I had a look a the latest patch, the test was failing because we now need to use the ContentModerationTestTrait to create the editorial workflow, which was introduced in #2952307: Move workflow config into standard profile

Should hopefully come back green now :)

jonathanshaw’s picture

Status: Needs review » Reviewed & tested by the community

@xjm in #39 suggested this should be won't fix or postponed, but asked for feedback on that.

#40, #41, #45 and #48 have some experienced core devs pushing back in favour of this issue, so setting for RTBC for @xjm to reconsider.

The last submitted patch, 45: 2873287-45.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. Still needs a CR
  2. +++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php
    @@ -194,7 +207,25 @@ public function save() {
    +      $original_content_moderation_state = \Drupal::entityTypeManager()
    +        ->getStorage($this->getEntityTypeId())
    +        ->loadRevision($this->getLoadedRevisionId());
    

    Note this is an uncached read. Is ->original never populated?

  3. +++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php
    @@ -194,7 +207,25 @@ public function save() {
    +    \Drupal::service('event_dispatcher')->dispatch(ContentModerationEvents::STATE_CHANGED, $event);
    

    Does dispatching an changed event for a creation really make sense? In order situations we're defining the before state as the initial state which is confusing. See #2914873: The "from state" used for calculating available transitions is changed when using the content moderation state widget and preview mode.

  4. +++ b/core/modules/content_moderation/src/Event/ContentModerationStateChangedEvent.php
    @@ -0,0 +1,103 @@
    +   * @return string
    +   *   The state the content was before.
    +   */
    

    Can be FALSE

xjm’s picture

Also #39 has not been addressed? There have been a few comments in favor of the idea of this issue, but no changes to the patch nor specific response to my points.

energee’s picture

I vote event instead of hooks, what is required to commit to core beyond #2873287-50: Dispatch events for changing content moderation states? Removal and upgrade path for hooks?

jonathanshaw’s picture

What is required are specific (and persuasive) responses to @xjm's points 3-6 in #39

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Berdir’s picture

Just a minimal update for D10, changed event base class.

pooja saraah’s picture

Fixed failed commands on #65
Attached interdiff patch

Anchal_gupta’s picture

I have fixed CS error. Please review it

pradhumanjain2311’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
15.54 KB
882 bytes

Try to fix PHPStan error.

pradhumanjain2311’s picture

Status: Reviewed & tested by the community » Needs review
Berdir’s picture

Fixing the dispatch call.

Status: Needs review » Needs work

The last submitted patch, 70: 2873287-70.patch, failed testing. View results

penyaskito’s picture

That also needed to happen in tests.
Fixed that, and the method signature forces us to return something (usually the event itself). This should be green.

Next step should be fixing the php10 deprecation warnings.

penyaskito’s picture

That was the interdiff only... not even properly named.

Status: Needs review » Needs work

The last submitted patch, 73: 2873287-content-moderation-events-72.patch, failed testing. View results

penyaskito’s picture

Rewritten the test based on #3306554: InvocationMocker::withConsecutive() is deprecated in PHPUnit 9.6 and removed from PHPUnit 10. Added a todo if this lands before that one. No deprecations anymore.
I feel like writing tests will be even harder now :-(

penyaskito’s picture

Mostly code standards, but I changed an exactly(5) to any() in previous patch and I reverted that back.

penyaskito’s picture

Status: Needs review » Needs work

Per #39 still NW.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Berdir’s picture

Status: Needs work » Needs review
FileSize
20.15 KB

Just another rebase, conflict on the save method changes.

smustgrave’s picture

Issue summary: View changes
Status: Needs review » Needs work

Updated remaining tasks to include #39 + change record.

gbotis’s picture

patch from #76 does not apply to 10.2.2

edmoreta’s picture

for 10.2.x use patch from #79

willeaton’s picture

Hi, I was looking for this functionality, its great for being informed of a transition event, but what about being able to veto the transition?

Use case: Product publication.

A user wants to validate a product ready for publication. The system needs to check that the product is really ready. Maybe they haven't filled in all the required fields for publication (fields which cannot be required to create the initial entity/node). Maybe they haven't prepared related content which is required for publication.

The system should be able to validate certain data before allowing the product to pass to a validated state.

Previously we used the "Workflow" module but we decided against it because the module doesn't seem to be maintained and the code base is still in a state of temporary migration from Drupal 7 style code. Content Moderation seemed to be the more accepted option however it is limited in this respect.

dww’s picture

@willeaton: You might find State Machine suitable for your needs. It provides / supports "Guards" which are plugins you can define to prevent specific state transitions if certain conditions are not met. But we're getting a bit off topic from this issue.

I also needed something like this for a project, but this issue seems a potentially doomed in deadlock between release manager and subsystem maintainer. I'm not sure I can be more persuasive than what @Sam152 already said in #40 and #45. Yes, a mix of hooks and events is somewhat crappy DX, but so is the current situation. I'm not sure how we provide 100% BC without a mix of both unless we want to make ContentModerationState public API. Drupal seems to love to provide a lot of different ways to alter the same thing 😅 so I'm not totally convinced that having both Events and hooks is really all that terrible. 😂

+1 to doing this. If I can find more time for a direct (and hopefully persuasive) response to every point in #39, I'll try.