Problem/Motivation
See #2755073: WI: Content Moderation module roadmap and #2721129: Workflow Initiative
Proposed resolution
Rename and drop-in Workbench Moderation an experimental module into core with the following changes:
- Replace moderation_state field with a computed field.
- Add ContentModerationState entity to link a specific entity revision to a moderation state.
- Updated views support for ContentModerationState.
- Add weights to moderation states
- Code clean up
- Coding standards
Remaining tasks
Review the code.
User interface changes
Adding new user interfaces for moderating states and forward revisions etc.
API changes
No API changes. Only additions isolated in the experimental module.
Data model changes
No data model changes. Only additional entities and fields.
Comment | File | Size | Author |
---|---|---|---|
#125 | 2725533-3-125.patch | 358.65 KB | alexpott |
#125 | 117-125-interdiff.txt | 29.73 KB | alexpott |
Comments
Comment #2
dixon_This plan still needs work.
Comment #3
dixon_Comment #4
dixon_Comment #5
fago>Proposed module name: Entity Moderation (entity_moderation.module)
As this is going to cover content entities and we have content translation module, it would make more sense as content_moderation module imo.
Comment #6
dixon_@fago That makes sense. I updated the proposal :)
Comment #7
dixon_Comment #8
Crell CreditAttribution: Crell at Platform.sh commentedThe current working plan (from discussion elsewhere) is to take Workbench Moderation 1.0 as is, rename it, and put it into core directly as an experimental module. We can then iterate as necessary to smooth out any rough edges and transfer some of its utility code directly into Entity API.
Tim Millwood has already started the rename work here: https://github.com/timmillwood/content_moderation
Is anyone opposed to this approach?
Comment #9
timmillwoodComment #12
dawehnerNice!
Comment #13
timmillwoodComment #15
timmillwoodTrying to address the failing tests.
Comment #17
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented#2753733: AccountProxy can do unnecessary user loads to get an ID was opened for the ConfigImportAllTest fail, and I implemented a workaround in the meantime. Let's see if upper-casing the module name in its info.yml file fixes the other test fail.
I also fixed a few small things that jumped out at a quick glance through the .module file.
Comment #19
larowlanJust a heads up that we're going to commit these to WBM this week
Comment #20
timmillwood@larowlan - Thanks for the heads up, I guess for now (until WBM 8.x-2.x) we need to re-roll all contrib patches against core, and all core patches against contrib.
Comment #21
timmillwoodLooking deeper into the failing test
Comment #22
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThis should do it.
Comment #24
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRemoved a lot of unrelated changes from the patch.
Comment #25
dawehnerThat seems totally fixable!
Does that really make sense? The least revision should not have any kind of configuration for the value.
Comment #26
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@dawehner, I agree, but then I wonder how did the 'value' key got into
core/modules/content_moderation/tests/modules/content_moderation_test_views/config/install/views.view.latest.yml
:I assume that's why the test is complaining about missing schema for 'value'.
Comment #27
Bojhan CreditAttribution: Bojhan as a volunteer and commentedIt would be worthwhile to have a discussion about this. About the scope, approach and get initial signoffs before proceeding. The idea of a plan issue to get that.
The idea of putting a patch in this issue at this moment in time, baffles me.
Comment #28
timmillwood@Bojhan - When discussing this with Alex and Catch we had verbal sign off to get Workbench Moderation module in as Content Moderation experimental module. This will help expose and test many core issues around this space.
That being said we should have more discussion around this.
Comment #29
timmillwoodPatch in #24 seems good to me.
Comment #30
dawehnerYou know I just looked quickly at the test coverage as well, and thought about fixing things correctly but andrei was simply faster/did it. Don't worry
Comment #31
Bojhan CreditAttribution: Bojhan as a volunteer and commentedThat's great, still needs product manager and subsystem maintainer sign-off :)
This received no UI review, so this cannot be RTBC.
Comment #32
jibranSome review points. Who is the subsystem maintainer here? We are missing MAINTAINERS.txt entry as well.
Can we generalize this comment?
Desc block is missing.
Issue link please.
More then 80 chars.
Don't we need issue links for these?
Why can't we use ['class', 'method'] here?
Desc is missing.
This should be injected.
Class doc missing.
Desc block is missing for vars.
Function doc block is missing.
Var desc is missing.
This is not right.
Who is I? Crell?
I think we don't use that.
Space missing.
Why can't we use ['class', 'method'] here?
More then 80 chars.
Commented code.
Wrong indentation.
Doc block missing.
I think we are moving to core now.
Desc line missing.
Desc is missing.
Can we do this now? Or at least have an issue.
Link please.
FQDN please.
Desc is missing.
Doc block is missing.
Desc is missing.
Links please.
Sorry what now?
Doc block is missing.
Desc is missing.
This should be multi line.
Commented code.
Comment #33
timmillwoodGoing to tackle all 36 issues @jibran awesomely brought up. I naively thought that as an experimental module we could just drop in Workbench Moderation as Content Moderation.
I will work with the Workflow Initiative team and Workbench Moderation maintainers to make sure we have suitable subsystem maintainers.
Comment #34
dawehnerCan someone please clarify what kind of feedback one is allowed to give? I'm asking about experimental modules in general.
Comment #35
dixon_The idea of this issue was to have this strictly as a planning issue, for needed sign-offs. But considering that the patch/review workflow already kicked-off on this issue, I'm moving the plan issue here: #2755073: WI: Content Moderation module roadmap
Comment #36
dixon_Updated the issue summary to follow a traditional implementation issue.
Comment #37
dixon_@dawehner In my opinion, the definition around what's ok/not ok for an experimental module is still not fully clear. But below are a few cut-outs from the meeting notes we took after the core conversation in NOLA:
The original notes are here: https://docs.google.com/document/d/17LIgHEXBbRm_IJeJRznlLzO5zQO21ImhvyPZ...
Based on the above, and various other conversations I've been part of, it seems like experimental modules are allowed a lot lower gates than we're used to in core. Basically to embrace the iterative part of this new proposed process.
So in my opinion, this seems like a good summary:
I think we need this formalized somewhere in the core governance documentation somewhere though...
Comment #38
catchI think what we're still missing (partly because we haven't done it yet) is the process of getting from experimental to stable release. i.e. we don't have a workflow for reviewing thousands of lines of code that works at all.
That could probably use a separate issue, or there might be a plan issue open covering some of it already.
Comment #39
timmillwood#32.8. Is a static function so can't use the service property.
I think I have covered all of the items, apart from some of the creating new issues for todos.
Comment #40
larowlanProbably should contact wbm maintainers to ask if they want to be listed in maintainers.txt, given its their work.
What happens to sites with wbm enabled? Two modules defining the same base field - do you end up with a field mismatch.
What happens to existing data if you disable wbm to enable this module? Do you lose all your existing data.
We need tests for that.
Comment #41
dixon_Tim and I have reached out to both agentrickard and Crell, and they both said they won't be able to do any day-to-day maintenance of the module and could therefore not be counted on as maintainers. So for now adding Tim into MAINTAINERS.txt makes sense to me.
The latest conversations that we had here at Dev Days (I will be posting the notes very soon) is that we should remove the UI for adding and managing state transitions from the experimental module in core. So WBM should remain in contrib and adding this UI ontop of the core module. So therefore it probably would make sense to keep any migration logic and tests for that in WBM itself.
Comment #42
larowlanWe need to at least test (even manually) what happens when we have two modules defining the same base field definition. We might need one of the two to check for the presence of each other before changing field definitions.
I'd be happy to pitch in too, given a large amount of the module was adapted from my code and I'm keeping an active eye on the D8 branch.
Ha ha, copy pasted from DER into moderation_state, into workbench_moderation and now into content_moderation.
Love it.
To get maximum use out of this module I really think we need #2702041: Add views relationship from content to latest revision in this patch too. I'm going to commit it to wbm tomorrow.
Comment #43
Crell CreditAttribution: Crell at Platform.sh commentedThis fills me with dread. We've tried to put "junior versions" of contrib in core before. It's always been a disaster. What's the reasoning for this? Sure, those UIs could be improved (what can't), but there's no reason to split the module in half while doing so. A Content Moderation UI module sounds like an awful idea.
Also, for the record, Dixon accurately summarizes my (lack of) maintenance capacity right now.
Comment #44
dawehnerWell, its the idea of an experimental module to not be complete. The idea is to get a simple version in, and then iterate on top of it. Its not meant to be used as stable module, or for example would be enabled by default.
At the same time we try to limit the amount of additional technical and product debt by keeping the UI as simple as possible, in this case, by dropping the less important part of the module, aka. the states and state transition UI. There is nothing which blocks you from creating custom states via YML files. The module though for itself is already helpful as the common default set is quite useful already.
Comment #45
Crell CreditAttribution: Crell at Platform.sh commentedHow does it increase tech debt to include a mostly-Drupal-default UI that we can then iterate on in core? All I can see this doing is creating more work and possibly ending up with a less-useful module in core at the end. An experimental module means the UI is subject to change, too, so we aren't committing to anything. Experimental or not, I see no wins in this approach.
Comment #46
timmillwood@larowlan - I'll happily add you to MAINTAINERS.txt in the patch.
@dixon_ @dawehner - I agree with @Crell. I think updating this patch to remove the UI, then creating WBM 8.x-2.x with only the UI will take a lot of time. This time would be better placed just updating the UI. At the moment we're not 100% sure what that UI might be so let's just get WBM in "as is" then iterate.
Comment #47
agentrickardI agree with Tim and Larry, above. Removing the UI and putting that in contrib seems like a poor use of time and a burden on maintainers.
Comment #48
webchickLeft a novella review of this patch over at #2755073: WI: Content Moderation module roadmap (spoiler alert: I agree with the last few comments), since it seemed more high-level about the scope of the broader sub-initiative.
In there I also suggested a couple of commit-blockers: 1) reducing the list of default states/transitions and 2) adding some means of listing content that's in a workflow state. I don't want to split discussion, nor create more work for people. Is the best thing to do mark this postponed until #2755073: WI: Content Moderation module roadmap is resolved and discuss the "spec" over there, or should we discuss it here, or..?
The only relevant technical piece from the review is that for some reason the "Content Moderation" menu item is not showing up under admin/structure. Probably something silly that's still not quite renamed properly yet.
Comment #49
larowlanthat's #2702041: Add views relationship from content to latest revision which we need to adapt here too
Comment #50
larowlan#2702041: Add views relationship from content to latest revision and #2708941: Allow roles to view but not administer moderation state are now in workbench_moderation in contrib
Comment #51
webchickSweet!! :)
Comment #52
Bojhan CreditAttribution: Bojhan as a volunteer and commentedA small note, we should be moving this to /config after commit. We have a actual category for this in Config designated especially for this type of configuration - it just took 6 years to use it :)
Comment #53
alexpottPatch attached:
ModerationStateTransitionStorage
the whole dance to usesetModerationStateConfigPrefix
is not required - see changes toModerationStateTransition::calculateDependencies()
- reduces unnecessary public APIThis is harder to change once in core. The second 'moderation' is just repetition... node types are node.type.ID not node.node_type.ID
Comment #54
timmillwoodComment #55
dawehnerAdded a new subissue to not let the module workaround the missing common status interface: #2757055: Add a EntityStatusInterface
Comment #57
alexpottPatched does the following:
new Class()
. In the case of InlineEditingDisabler this functionality was just moved into the .module file since the class / service are just an unnecessary layer.The first interdiff is relative to #53.
Comment #58
catchWe should open a side issue for the moderation state tracking.
Since this is a field on entities, it would be easy enough via the API to make a forward/older revision in a non-published moderation state the default revision, without updating the moderation state, creating a mis-match. Not sure what/if the answer to that is but worth discussing on its own.
Comment #59
alexpottComment #60
alexpottMoved paths from
admin/structure/content-moderation
toadmin/config/workflow/moderation
Comment #61
webchickJust a quick note that the bug I noticed in the last version I tested with the menu item not being visible is fixed now. :)
Comment #62
BerdirHave been looking through the code a bit, feedback below. The most important thing is the first one, that's my biggest concern. The second is that I don't see the capability to uninstall module again as far as I see. Seems like a one-way street right now, which seems especially problematic given this is an experimental module where we don't provide an upgrade path (I suppose?) and people might be required to uninstall it again? Unlike our existing experimental module, this isn't nicely separated and removeable like migrate or bigpipe but *deeply* integrated into the content. I'm expecting some interesting challlenges there. But I suppose that was already discussed.
The third point (which just like the second is not mentioned below anymore) is that I didn't see any logic for entity types that are added after this module was installed, but maybe I missed that, it is a lot of code ;)
The other points are mostly smaller things, but I was looking through the code anyway and noticed them, we can still fix them later if not important enough for now.
so all revisionable entity types with a bundle get a moderation state?
I don't really like this. There are many examples for entity types where this really makes no sense. Take paragraphs, field collection and similar "composite entity types" which only exist in the context of e.g. a node. They have no reason for having their own revision handling/moderation, each node revision also has corresponding paragraph revisions and they're managed as a whole.
Users might get revisionable soon and while they don't have a bundle and are therefore currently excluded from this (why? custom entity types might not have bundles but still want to use content moderation, we could also support the settings we need as entity type annotations for example) are another example for an entity type that has revisions but doesn't need moderation IMHO.
I think as a minimum, we should support an annotation key so that certain entity types can opt out of this. or even make this configuration so that users can decide what content they want to have moderated. Like content_translation does.
that's not what the code is doing?
is it worth checking if quickedit is enabled before those checks? unset() doesn't result in notices, no idea how expensive those checks are.
don't really understand the pattern with that create helper function (why not a service?)
worth checking if $form_state->getFormObject() is actually an entity form before calling this?
we usually don't shorten variables like this.
For this to actually work, we'd need to implement the node grants system, so that e.g. admin/content would shown unpublished content. How are we going to deal with that?
why is the alter hook not also in this file?
we had some serious performance issues initially in 8.x because the query to check if a node had revisions was extremely slow due to missing indexes. has this been checked here? (I understand performance is not a concern for an experimental module apparently, but sooner or later, we'll have to figure this out)
also not something we usually do IMHO
The method yes, but an entity key status is more or less a unified concept although not widely used in content entities. Could be done based on that.
$to_check is a strange variable name for an entity.
that's not how this works :)
Keeping the initial check outside of this method would allow to type hint on what we actually require.
those method names make no sense to me. both are entity types, one is content and one config.
All those "stupid core forgot to do this and that" are a bit weird now that this is in core (or will be) ;)
shouldn't be necessary.
I don't think this does anything, not being exposed is the default behavior
same here.
code and description doesn't match? also isn't this constraint always added above?
fixed how and why? That's the point of having that.. also not valid to add docs to @inheritdoc
usually we just use string casting for this I think. We also do this in lots of places without extensive comments, so not sur it is necessary here.
don't understand this todo, this works as defined?
doesn't seem to do anything special, could use the default delete from?
the same entity type vs entity naming that still doens't make sense to me :)
an entity query object is not re-usable, it's not a good idea to inject that.
You can also do getQuery() on the storage if you have that already, then you can avoid this additional argument completely
strange name as we call this LocalTask in code, not tab?
Comment #63
larowlanThanks @alexpott, this was my code back from moderation_state module, nice to know there's a better way
Comment #64
Wim LeersI reviewed this code from the POV of Quick Edit, cacheability and access control in particular, and consistency/maintainability in general.
I refrained from posting nitpicks, of which I could easily post 100 or so. Lots of code formatting problems.
I think this is the first time we would use
camelCase
in config.Do we want that?
(Grepping the codebase for the regexp
[a-z]+[A-Z]+:
on all*.yml
files confirms what I said.)This sounds scary.
This asset library version seems wrong.
Should link to an issue.
(Quite a few todos should.)
This still links to the
workbench_moderation
docs. Perhaps that page can be reused, but then its alias should be updated.The comment does not match the logic.
Do we have test coverage for this, also in relation to translations & revisions?
Because
editor
module also implements these hooks and has several bugs despite test coverage (boo @ me!), so I just want to warn you about that because these hooks do work in unexpected ways.See #2708411: [PP-1] editor.module's editor_file_reference filter not tracking file usage correctly for translations + #2729953: Clarify handling of multiple references to the same file from entities. (I know, not exactly the same, but IMO good to double-check those aspects.)
Cacheability metadata here is wrong.
view
case, you're depending on the entity, but the entity's cacheability metadata is not added to the access result.getValidTransitionTargets()
, and it apparently depends on the Entity and User objects (both of which have cache tags), and I suspect it further depends on configuration (which also has cache tags). Yet despite so many things that could change (Entity/User/Config) being involved in deciding what the access result is, there is no cacheability metadata whatsoever. That cannot be right.Finally, let's use strict comparisons.
You only need to specify this route option on routes that have a path that does not begin with
/admin
.This looks much better.
For the
@todo
: AFAICTModerationInfo
does not look at any configuration, it only looks at the data stored in the entity. Therefore no additional cache tags are necessary.Eh… this looks bizarre. But probably a necessary evil.
This does not inspire confidence, and suggests a lack of test coverage.
$this->t()
And that weight seems… very specific. It should be documented why that particular weight was chosen.
Fancy! :)
This will be the first use of
yield
in Drupal 8.Comment #65
timmillwood#62 feedback:
We should probably work on an uninstaller before 8.2.x as a priority.
1. Yes, all revisionable entity types with a bundle get a moderation state. However being moderatable is disabled by default and needs to be enabled within the bundle settings. It was discussed about making revisionable entity types without bundles moderatable, but where do you add the settings? It was a simpler option to just add it for bundlable entity types. Maybe adding an opt-out annotation would be good.
4. They used to be services, but being standard classes makes it simpler, doesn't add unnecessary services, and doesn't give them impression these services can or should be swappable.
All other items look to be things that should be addressed, but are they commit blocking? I feel many of them would be easier to address as sub-issues rather than keep re-rolling this already unwieldy patch.
#64 feedback:
1. yes it is, let's just get it committed, then fix all these items in sub-issues before 8.2.x release.
3. is it? We're just adding a field to all revisionable & bundlable entity types.
6. yes, this is good enough to make core help tests pass, but we should update the docs before 8.2.x release.
Comment #66
dixon_I agree we should look to fix the uninstall issue and perhaps also add an annotation key for opting out of moderation, as Berdir suggested.
After these fixes I would really encourage getting this patch committed and deal with the last reviews and nit picks in a follow-up. It's hard to both re-roll and review a big patch like this.
I have created both the follow-up issue and an initial draft change record for this: https://www.drupal.org/node/2757719
Comment #67
Crell CreditAttribution: Crell at Platform.sh commentedRe uninstalling: Yeah, that's a problem. The issue is that:
1) Core doesn't let you uninstall a module that provides a field if that field is in use. (Reasonable)
2) In use includes on a non-current revision. (Reasonable)
3) This module forces the use of revisions, which therefore means lots of old revisions. (Obviously)
4) Those old revisions have the moderation_state field on them, provided by this module. (Obviously)
5) You can't edit an old revision. (Obviously)
6) So... as long as those old revisions exist, and have a moderation_state field, which they will always have, the field is always in use, and so the module rightly cannot be uninstalled! (Crap)
For WBM, we punted and decided we didn't want to deal with that for 1.0. The only way to cleanly make the module uninstallable is a cleanup script of some kind that disables moderation for any entity/bundle that's using it, then saves a new revision without that field on it, then deletes all old revisions of any previously-moderated entities. At that point the field usage should be purged, so Drupal should allow the module to be uninstalled.
If someone knows a better way than that, I'd love to here it because that was a thorn in our side while developing WBM. :-(
Incidentally, I am reasonably sure (although not 100%) that the module does not add the moderation state field to all entities unconditionally; it just adds them to those where it's been enabled. I may be wrong on that, though, but I think that's the case. (That part of the code dates to larwolan's original and I didn't 100% grok it, to be honest.)
Wim: That was like my 3rd attempt to have a legitimate "yield" in the module. :-) Yay for more advanced language toys in core!
Berdir: A number of those hooks are services in WBM. Apparently alexpott wanted them taken out and done the Drupal 7 way (per #57). I do not know why, and disagree strongly with that position. "Why would you swap it?" is a poor reason to avoid a service.
Comment #68
alexpott@Crell no interfaces and only ever located through \Drupal::service() is why these shouldn't be services. If there really was a use case for it to be a service they'd have interfaces and be injected properly into something.
Comment #69
timmillwoodNote: moderation_state field is added to the database table before making a bundle moderatable.
Comment #70
Crell CreditAttribution: Crell at Platform.sh commentedalexpott: Half of those were bridging off of hooks to classes. We've been talking in another issue about making it possible to register services straight to hooks without having the function at all. That would allow "just drop the function and add a tag" upgrades. Adding an interface to them suits me fine.
Comment #71
catchNot being able to uninstall this needs to block the initial commit. We're OK with experimental modules themselves having serious bugs, or the upgrade path for them being uninstall then re-install, but the inability to uninstall prevents even that from happening. Even if people take our advice and don't use alpha-level experimental modules in production, it's reasonable to develop and un-launched site with them, and that un-launched site may want a canonical database. This is already covered in https://www.drupal.org/core/experimental#requirements
So marking needs work for that. We can work on that in #2757119: Data integrity and uninstall issues with moderation state field (which I'll re-title).
Comment #72
cosmicdreams CreditAttribution: cosmicdreams commentedShould we use the PP-1 syntax for this issue then? To make it clear from the title how many blockers this issue has
Comment #73
larowlanI think it'd be wise to step away from maintaining this, realistically I'm spread too thin. Can my name be taken out in the next re-roll.
(Discussed this with @timmillwood on irc first).
Comment #74
jhedstromThere are quite a few folks putting effort into issues in the Workbench Moderation issue queue. However, there hasn't been a commit in over a month, so I'm wondering if that's due to the assumption that this will go in soon?
Comment #75
larowlan@jhedstrom no, I intend to keep committing stuff to wbm.
content moderation won't be for production sites (experimental) whereas wbm is.
Comment #76
jhedstromThanks for the clarification @larowlan.
I'd like to propose a potential alternative approach here.
Rather than trying to get the current workbench moderation module in as a single patch, in its current state, how about tagging crucial issues in the WBM module queue, and focus on those for say a month or so. This will a) get more eyes on those issues, and b) once they are resolved, this patch can go in sometime before 8.2.0 beta with minimal review of the giant patch, since issues will have been fleshed out individually in that queue. At some point after that, an upgrade/migration path in WBM can be made to the now identical core module, and existing sites can readily move to that.
Going even further, since the contrib namespace for content_moderation is currently listed as unsupported, that namespace could be taken over, and as issues are resolved in WBM, they could be immediately mirrored there. Then the final patch to core is even more readily reviewable. The added benefit there is that new sites could start to use that module instead, requiring no migration in the future from WBM.
Comment #77
timmillwoodThought it was time for a quick progress patch.
Comment #78
Wim LeersCould you provide a summary of the changes?
Comment #79
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@Wim Leers, most of the stuff that can be seen in the interdiff from #77 is the work from #2757119: Data integrity and uninstall issues with moderation state field, which changed the architecture of the module to store state transitions in a new content entity instead of in a field on the moderated entity.
Aside from that, the code has been cleaned up a lot all over the place and I also fixed most of your review points from #64. Here's an interdiff for that review, it also contains a few unrelated cleanups but it should be pretty easy to follow the fixed items.
Comment #80
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedOops, forgot to attach the file :/
Comment #81
alexpott@Wim Leers also there's the commit history available at https://github.com/timmillwood/content_moderation/commits/master
Comment #82
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedTwo major usability issues have been fixed, #2757349: WI: Deal with scalability issues in the UI and #2757275: Decide on default moderation states, so here's a new patch with interdiffs for both of them.
Comment #84
tim.plunkettJust for the record, this is duplicating
$allow_role_labels = user_role_names(FALSE, 'use ' . $transition_id . ' transition');
Comment #85
timmillwoodUpdating patch with the latest commits from https://github.com/timmillwood/content_moderation/commits/master
Comment #87
timmillwoodFixing the schema issue from #85.
Updating paramconverter to only load the latest revision if isRevisionTranslationAffected() as mentioned in #2766957: Forward revisions + translation UI can result in forked draft revisions.
Comment #89
timmillwoodFixing tests, and updating the change in #87 to do isRevisionTranslationAffected() on the correct language.
Comment #91
hass CreditAttribution: hass commentedGreen, but failed???
Comment #92
timmillwoodAdding a test to test the translated forward revision issue in #2766957: Forward revisions + translation UI can result in forked draft revisions.
Comment #94
timmillwoodPassed second time around.
Comment #95
timmillwoodAfter working through #2766957: Forward revisions + translation UI can result in forked draft revisions in more detail, I am standing by #82 as my preferred solution.
Comment #96
timmillwoodThe biggest blocker to this, #2688945: Allow removing a module's content entities prior to module uninstallation, has landed today.
IMHO we should be good to go with this!
Comment #97
dawehnerIt would be kinda great to have some sort of quick issue summary about the architectual design of the module or at least some differences between the contrib and core one.
Comment #98
timmillwoodUpdated summary with high level changes:
- Replace moderation_state field with a computed field.
- Add ContentModerationState entity to link a specific entity revision to a moderation state.
- Updated views support for ContentModerationState.
- Add weights to moderation states
- Code clean up
- Coding standards
Comment #99
xjmThe core committers (@alexpott, @xjm, @Cottser, @catch, @effulgentsia) discussed this issue and agreed that this is a high-priority feature for the Drupal 8.2.0 release. We agreed to make it a beta target (that can be committed after the first beta but ideally before the second) in order to take the time to get this right, if it is ready within the beta phase.
Comment #100
timmillwoodAdding what I hope is the final patch to remove @larowlan from MAINTAINERS.txt as requested in #73.
As long as this passes tests I will then RTBC so we can commit before beta freeze.
We should give credit to more than those who provided patches here, an maybe even those who helped via #2766957: Forward revisions + translation UI can result in forked draft revisions too.
Comment #104
timmillwoodI'm struggling to recreate these failures locally.
Comment #106
larowlanSome observations
Nit: do we need these?
These are old comments from moderation_state.module
New url needed?
This runs once for each entity in a list. Which means we're creating several instances of the helper class. Could it be a service instead?
If this were a service we'd only create one in the live cycle of a request. As it stands we create several just to save a single entity. One in presave, one in insert|update, so on.
Creating one of these helper objects for every entity being viewed seems like overkill? Can it just be a service?
Do we normally comment these?
Should we point to the code in the entity handler that uses this in its instanceof checks?
Is this coming? I think the index would be a blocker. Also nit > 80 chars
We're in core now, should we be referencing an issue to fix this rather than saying 'this is core's fault'?
Do we have an issue or is this no longer relevant?
We have the entity type manager injected, should we be using the storage handler direct instead of the static method?
Do we have a test for this?
This needs to reference an actual issue or be removed, we can't blame core from core.
Should we document why 27 is needed? Should we make it a constant? Seems magic
This is an old comment from moderation_state.module, we have a custom widget now?
Same again, we should be linking to an issue instead of blaming
The language here isn't consistent with core's commenting
These are old moderation_state comments I think
Still open?
We should add an issue for this and point to it here
An old comment from moderation_state.module
nice
More old moderation_state.module comments :)
nit
Comment #107
alexpottFixing the fails. Will address #106 later.
EDIT: To explain my testbot fails and locally does not - #1920902: Add a Drupal Yaml wrapper so we can default to PECL Yaml component if it is available - different ways of reading YAML. I wonder what the spec says about duplicate keys and which one is doing it right.
Comment #108
alexpott1. Seems harmless and breaks it into sections.
2. Agreed - removed.
3. I think we should have a followup to get this right once the module goes in. Removed the link to workbench_moderation since that's just wrong.
4. We moved away from services for responding to hooks since this pattern is not set in core yet. Let's consider our options once this patch lands.
5. See 4.
6. See 4
7. I think in this case they are useful - kinda like separators for the different sections
8. Not sure what you mean - we don't do that on any other entity interface
9. Removed the @todo's and added the necessary stuff to make the index
10. Let's fix this in a followup
11. I think this is all related to the critical #2766957: Forward revisions + translation UI can result in forked draft revisions - I think this should be dealt with post commit.
12. Sure why not.
13. I think this is a follow-up
14. I think this is a follow-up - to find/create issue and adjust comment
15. I think this is a follow-up
16. Removed
17. Adjusted the language to just explain.
18. Adjusted the language to just explain.
19. They still seem relevant - let's handle this in a followup
20. Yes still open and still very tricky.
21. Removed - what's in core is in core. That's what we have. If someone wants to file an issue so be it.
22. I think we should leave all the
// @todo write a test for this.
and file a plan to remove them and add (or determine if we already have) test coverage.23. :)
24. See 22.
25. Fixed
Comment #110
alexpottSo be it let's add a link in the the hook_help() implementation.
Comment #111
timmillwoodThink we're good to go.
Lots of follow up filed and still to file, but for now I think this is ready for commit to 8.2.x.
Comment #112
catchTrying to give this a full look over. I didn't get anywhere near finishing, posting this and I'll come back to it later. None of this is blocking and it's of varying levels of nitpicking.
This should normally have a link to permissions and configuration, doesn't block initial commit but should block stability.
I'd rather see this handled in hook_requirements() or use #746752: New "conflicts" property for .info.yml extension files if we had it in core. Just hiding it could also lead to confusion if people expect it to be there.
I can see it getting confusing between this new permissions, 'bypass node access' and 'administer nodes'. That's not entirely the fault of this patch, it's already confusing in there.
Could do with a followup to discuss the implications of this.
Why is this necessary as a separate permission?
Why is this necessary vs view all revisions?
Could we use the new auto-route for this?
Not sure the 6 lines of duplicate code this saves is worth the 12 lines to define the function.
Do we really need the CSS in the module?
parameterized.
+1
This is probably going to run into #2528314: template_preprocess_node() does not add cacheability metadata. Not the fault of this patch.
Could use a follow-up, - harder to do once we need an upgrade path.
This is tricky and could use docs for why it's necessary.
Won't it be necessary for progammatic saves?
Minor, but I'd probably make this #access false to have less on the form.
These could use more high-level docs explaining what the entity does, or an @see to somewhere that does that.
How can you get into this situation? Shouldn't it throw an exception or at least trigger_error() if we get here?
This is where the lack of an entity status API bites us. I'd trust $node->published over the moderation state entity here.
Could probably be array_walk() rather than foreach? (and below)
fancy.
Comment #113
alexpottI'm pretty sure that #2362435: When viewing a revision, the Quick Edit, Edit, and Delete contextual link operations are available, but should not be covers the case of #112.2 and therefore this code is unnecessary. I think removing it prior to commit might be a good thing.
Comment #114
catchAnd some more - again I think this is non-blocking.
The main-substantive question I have is about the transition storage. The split between state config entities + transition entities + third party settings for bundles seems a bit fragmented.
Also these transitions are global - what happens if a site wants different transitions (and states) for different entity types?
Wondering if we could just ditch this and have it displayed full view mode?
Is there an issue for this?
Class moderationstateform is a moderation state form class.
Is moderatable a word? Should this be moderated instead?
Also uses moderated here.
Should this be explicitly marked @internal or we don't care? Some of these aren't specific to content_moderation and could be moved into core.
moderatable or revisionable?
I'm sure this weight-on-config-entities issue has come up before, but can't remember where exactly.
What is this WBM you speak of?
Not sure why this is necessary - the entity table itself has the same information.
This comes back to my earlier question about transitions. So you can set moderation states per bundle, but not transitions. Part of me wonders whether it wouldn't be simpler to just store the transitions in bundle third party settings rather than the combination of multiple configuration entities plus this setting referencing the states.
Do the third party settings get cleaned up when a state is removed?
This covers permission question above.
Maybe'isTransitionValid' to differentiate it from userMayTransition.
Comment #115
catchOpened up a follow-up issue for the states/transitions stuff at #2779647: Add a workflow component, ui module, and implement it in content moderation. I don't think that needs to block commit, but would be good to have a proper look at it after since it'll need to be decided before we get out of alpha.
Comment #116
alexpottThanks for the review @catch. We've got a metric tonne of minor followups to create from this issue. Most minor and some more substantial in terms of architectural changes (#2779647: Add a workflow component, ui module, and implement it in content moderation) or bugginess (#2766957: Forward revisions + translation UI can result in forked draft revisions).
I'm +1 on the rtbc I think it is time to start iterating on the functionality in core.
Comment #117
alexpottHere's a few of the nits from @catch's review and things that PHPStorm noticed.
The big change is a find and replace on 'moderatable' to 'moderated' since the first one is not a word. I think the code reads better for using a real word.
Also addressed in #112.2 which allows us to remove content_moderation_module_implements_alter().
And parametrized is a word apparently and preferred in core (8 v 1)
I've left all the other points of catch's review for followup because either they require discussion or are nicely self-contained.
Comment #118
alexpottCreditting some of the people on this issue - this process is by no means complete.
Comment #119
alexpottComment #120
Crell CreditAttribution: Crell at Platform.sh commentedIf I recall, at least when I was working on the module "moderatable" meant "we could apply moderation to it". "moderated" meant "we have done so". Eg, a node type that doesn't have moderation enabled is moderatable, but not moderated.
That may have changed in Tim's updates, but at least originally there WAS a distinction between the two. (And yes, moderatable is totally a word in English.)
Comment #121
alexpottI can't find moderatable in the first three online dictionaries I looked in.
Comment #122
alexpottThat said it seems that adding -able is a productive process and could be considered allowed because moderate is a transitive verb - http://english.stackexchange.com/questions/132535/to-be-able-to-toggle-s...
Comment #123
Bojhan CreditAttribution: Bojhan as a volunteer and commentedThis is not "experiment module" talk anymore :P
Lets get it in! :)
Comment #124
jibranI have done a final review and found some minor points.
We should use an interface here.
I see a new module here dynamic_entity_reference_revisions. :D
> 80.
I didn't know we can use * like that in comments.
Is there an issue to fix this? We should add @todo here.
I wish we could use class name constants here.
Is it still pending?
Can we have a d.o link please?
Shouldn't this be TRUE?
We can improve this comment.
Comment #125
alexpott@jibran this is an experimental module - the code does not have to be perfect. We have time whilst the module is in alpha to make any change we like. Also in general if you want to post nitpicky reviews I encourage you to post a patch with the review. There is general confusion over the level of review an experimental module is supposed to have but I'm prettyu sure that this one has had plenty.
Anyhow,
1. This can be a followup
2. Maybe
3. Removed comment that's been done and created #2779931: Add storage exception that enforces unique content_entity_type_id and content_entity_id on the content moderation state content entity, and add access control handler to forbid all access
4. Fixed
5. Adjusted comment to not be about "in core" but I don't think this actually needs an @todo and an issue it is just explanation of what the code is doing.
6. Okay
7. Yes
8. Created #2779933: Check for missing test coverage in the Content Moderation module and added to @todos
9. That's the stuff of followups if correct - certainly does not need changing now.
10. I think I want to leave this comment as it is for now. I think it represents a mis-understanding of how the revision of the content moderation state is related to the revision of content entity it is related to. They are not really related at all.
I've also chosen to revert the 'moderatable' to 'moderated' change. This can also be discussed after commit. It is annoying when IDEs pick up this as a spelling mistake and I think the change is worth it. But @Crell's point about some of the is..Moderatable functions needing to be converted to canBeModerated or canModerate is valid and therefore the change is not a simple find and replace.
Comment #126
alexpottCreated #2779939: Cleanup the ModerationInformationInterface to address the moderatable issue
Comment #127
jibranThanks @alexpott for fixing the review.
I didn't change the status of the issue. IMO that means the review can be ignored or some review points can be skipped. I should have mentioned that in my review. I know my review was bit too much and I didn't want to disturb the development flow of the issue that's why I didn't upload the patch.
We just need (new) follow ups for 1, 7, 9 with links to the patch and we are good to go. yay!
Comment #128
swentel CreditAttribution: swentel commentedNo code review, just a + 1, nicely done! One thing that came to mind was the revisions overview page. I'm not sure whether this is discussed somewhere or not already (here or a different issue, didn't really find something on a quick search), but it feels like that page could potentially be taken over by content moderation to show the state of the revision. Because you can set previous revisions of any state back to the current revision, but that doesn't necessarily sets that revision to 'live', because you might be manipulating a draft revision. While nothing breaks, it confused me a bit since I was able to set a early draft back to the latest revision which is also the live revision and then the 'Latest version' tab is the same. (hope that latest sentence makes sense). Anyway, should not hold up commit!
Comment #129
webchickUnless I missed it somehow in testing, we seem to still be missing a way to view moderated content on e.g. admin/content.
Comment #130
catchOpened #2780613: Ensure that content in moderation can be found in the admin UI easily for webchick's comment in #129.
Comment #135
catchOK there's lots of minor and major follow-up work to do here, but already a lot of progress since this was proposed, and it'll be easier to review as individual patches with the code in core, so I've gone ahead and committed/pushed to 8.3.x and 8.2.x
Comment #136
xjmComment #138
benjy CreditAttribution: benjy at PreviousNext commentedBetween #60 and #77 it seems that all the events were removed. Is there an issue to add those back or documentation as to why they were left out?
Comment #139
timmillwoodModeration states are created and updated by using the Content Moderation state entity, therefore entity hooks can be used.