Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
The concept of workspaces and site-wide previews apply only to revisionable and publishable entities. However, it is very easy for site editors to miss this point and change some config values in a non-default workspace, for example adding a block in a Stage workspace, thinking that it will not show up in the Live workspace.
Proposed resolution
Figure out a way to communicate this and prevent any changes that would leak into the Live workspace.
Likely candidates:
- config entities/objects
- state
- path aliases
- others?
Remaining tasks
Discuss.
User interface changes
Yes, TBD.
API changes
Nope.
Data model changes
Nope.
Comment | File | Size | Author |
---|---|---|---|
#55 | interdiff-55.txt | 1.96 KB | amateescu |
#55 | 2975334-55.patch | 19.76 KB | amateescu |
#52 | interdiff-52.txt | 3.46 KB | amateescu |
#52 | 2975334-52.patch | 19.28 KB | amateescu |
#44 | interdiff-44.txt | 3.64 KB | amateescu |
Comments
Comment #2
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedMy initial thoughts for this problem were to show an error message and reject the validation of every form which doesn't deal with a revisionable and publishable entity.
However, as good as it was looking in the admin interface, the frontend would get terribly broken for small forms, like the one from the Search block.
Example error message on the admin side, when looking at the "add new term" form:
And an example on frontend side:
I think it's pretty obvious that this approach won't fly, so we need to come up with something better. Any thoughts? :)
Comment #3
timmillwoodWe could handle things in a similar way to config read only (https://www.drupal.org/project/config_readonly) by disabling the submit.
To get around the search form issue we could do this only on entity forms? and show as a drupal_set_message() rather than an inline error.
Comment #4
webchickFrom a UX POV, I think it would be useful for it to just "403" access to the offending link/form without giving the ability for users to even see it. Greying out a submit button 3 page scrolls down when you've already spent 15+ minutes entering content into form fields is pretty frustrating... and little errors on top of the page are easy to miss/bypass especially in an admin context, where your site may be "perma-warning" you of not-that-bad things like a missing ImageMagick, or what have you.
So for example, the button label on the term overview page could change from "+ Add term" to "+ Add term (Live only)" and it could be grey instead of blue and un-clickable.
Comment #5
timmillwoodWon't a 403 beg the question, "Why can't I access this?", though I guess they won't know they can't access it as they will never see the link, thus never seeing the 403.
Comment #6
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedHere's a patch that implements @webchick's suggestion from #4 and denies access to any other operation than
view
andview label
in a non-default workspace.This only fixes the problem for entities, we still need some low-level handling for config and probably state as well.
Edit: before going too deep into this solution, let's wait a bit for some feedback from the UX team :)
Comment #11
webchickWe discussed this on a call, and there was consensus (albeit somewhat teeth-gnashingly :D) on solving this at an API level being a beta blocker, vs. solving it at a UI level being a separate concern. So I think we need a postponed, "major" follow-up issue for the UI, and focus this one on preventing users from ending up in data loss land.
Comment #12
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThis patch adds multiple protections for preventing data loss/exposure:
- a user-friendly form validation error for every for config or entity form of a non-revisionable and non-publishable entity type
- a not-so-friendly exception in
hook_entity_presave()
which prevents any (non-rev, non-pub) entity save from going throughThe configuration system doesn't have any pre-save event in
\Drupal\Core\Config\ConfigEvents
, so there's not much else we can do for them..Comment #14
effulgentsia CreditAttribution: effulgentsia at Acquia commentedDo we also need to do the same for predelete()? Are there other considerations for how deletions are done while in a non-live workspace?
Open a new issue to add it?
Yeah, how should we handle these? Do we also need a preSave() for them or is there another way?
Comment #15
plachWe're still talking about experimental code after all, if we're able to cover content entities + config IMHO we're already good.
Of course if Workspace is aiming to provide real site previews, then we'll need APIs to cover not only config but state revisioning and who knows what else.
Comment #16
plachEntity schema revisioning maybe 😱
Comment #17
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedHere it is: #2983266: Add PRESAVE and PREDELETE config events :)
I wrote a read-only state implementation (see attached interdiff) but I quickly realized after trying to clear the cache that core is using state mostly as a "poorman's cache" system, given that the following state keys were being set after the cache clear:
So I don't think we can (or even should) prevent state calls from going through.
Also, I wouldn't block this issue on #2983266: Add PRESAVE and PREDELETE config events because I've no idea if that can go through before 8.6.0-alpha1, and at least we have the form-level protection in place here.
Comment #18
effulgentsia CreditAttribution: effulgentsia at Acquia commentedThanks for opening the issue. I agree it's not a blocker for Workspaces reaching beta. Possibly should be a blocker to Workspaces reaching stable, but we can decide on that later.
Comment #19
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedGood catch, we do need the same protection for predelete().
Comment #21
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedWhat happens in #19 is very interesting! Because we are switching the test entity type to
entity_test_mulrevpub
, which has workspace support whileentity_test_mulrev
didn't, we now have three more joins to theworkspace_association
table, which breaks down MySQL for some reason (too many joins?).I've opened a separate issue to track this problem and try to improve the number of joins we do on the
workspace_association
table: #2983639: [PP-1] Figure out a way to not join the workspace_association table for every duplicate base table join of an entity query, but for now I don't see any other option than to comment out a couple of query conditions.Comment #22
catchPath aliases are neither configuration objects nor entities, so I think they'll need their own special handling?
The approach here seems fine to me in general, is the idea that the UX issue and implementation would block a stable release or just be 'major'?
Comment #23
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedGood thing we hit this before with CM, so we can take advantage of the validation constraints written in #2856363: Path alias changes for draft revisions immediately leak into live site, #2858431: Book storage and UI is not revision aware, changes to drafts leak into live site and #2858434: Menu changes from node form leak into live site when creating draft revision, we just need an entity builder which sets the entity as a pending revisions if the user is in a non-default workspace :)
For either option, my personal opinion is that time would be better spent on fixing the underlying "problems", e.g. convert path aliases to entities, add workspace support for config, etc.
Comment #24
effulgentsia CreditAttribution: effulgentsia at Acquia commentedLet's add a protected static function for returning this hard-coded list.
Let's add a test to ensure this actually happens when expected.
Add "be" to the beginning of this line.
1. This needs a comment for why we're excluding Views Exposed forms.
2. By catching all config forms, we can't click "Clear all caches" on
/admin/config/development/performance
from a non-live workspace. Is that what's desired? I wonder if there are other config forms (or buttons on config forms) that don't actually modify config that we should exclude in some way.3. For forms that are neither entity forms nor config forms, they also pass the first part of the if statement, so this means all sorts of forms that don't change config are blocked by this. E.g.,
/search/node
. However, there are also plenty of forms that aren't ConfigFormBase forms but that do change config: e.g.,/admin/modules
. So this is tricky. I wonder if we should add some API for forms (or form buttons) to identify themselves as workspace-safe, so that both core forms like Search and various contrib forms can opt into that to bypass this validation.Should we retain test coverage for 'entity_test_mulrev' and assert what we now expect for it?
Comment #25
effulgentsia CreditAttribution: effulgentsia at Acquia commentedSo, forms don't run into the exception (the first hunk), since they're caught by the validation (the second hunk). But what about REST / JsonApi? Will they need to catch this exception and transform it to a friendly error response? Pinging @Wim Leers for input.
Comment #26
Wim LeersReviewed the entire issue. Things that stood out:
save
operation is a problem, but alsodelete
.State
key-value pairs that you point out: does that mean we should make those per-workspace? Also, at least in the case of CSS/JS aggregation, I think we could/should disable aggregation while looking at a workspace?Patch review, which also addresses #25:
These would also be invoked for REST/JSON API/GraphQL. 👍
If we need all this logic to prevent/inform the user upon validation of the form, then why don't we use this exact same logic to instead disable the form when the user accesses it? We can just do a
drupal_set_message(…, 'error')
with the same message if this condition is met, can't we?It'd be great if we could add a comment documenting why we cannot rely on
EntityOperations::entityPreSave()
to throw itsEntityStorageException
with basically the same error message.(It's because that exception only gets thrown upon submission of the form, at which point we can no longer transform that exception into a validation error, right?)
This is not a pattern we have elsewhere, but I like the DX benefit ❤️ 👍
I was wondering why we're only doing this for deleting.
Then I realized: we're only doing validation when we're about to save a set of values for an entity: when creating or updating.
But when deleting, Drupal doesn't do any validation. Hence validation constraints don't run. Hence the need for Workspace to handle this in a special way.
So, to answer #25:
EntityStorageException
, so that it becomes possible for them to catch Workspaces-specific storage exceptions.Ideally, they wouldn't be exceptions thrown during pre-save or pre-delete stages, but during validation. However, as pointed out above … Drupal doesn't do validation of about-to-be-deleted entities… and that's of course not Workspace's fault!
create
,edit
anddelete
links while accessing entities in the context of a workspace, and those links would be present in the context of the default workspace (which matches what #4 + #5 describe).Comment #27
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThank you @effulgentsia and @Wim Leers for the reviews!
Re #24:
1. Sure thing, moved that to a static helper and also added an alter step for it, so people can add their own entity types to the list.
2. and 5. Good point! Brought back the
entity_test_mulrev
entity type and wrote test coverage for our exceptions.3. Done :)
4. I agree that we need to let people alter the list of forms that are safe to edit/submit in non-default workspaces, so I also moved this part to a helper function and added an alter step for it.
If we're fine with the "whitelist entity type ID|form ID alter" approach, I'm not sure whether we want to put them in a
workspace.api.php
file since all these protections are meant to be temporary.Re #26:
1. I like the idea to have a workspace-specific storage exception! Done :)
2. Sure we can, and it's quite helpful now that users are able to alter the list of form ID which are "workspace safe".
3. Forgot about this one, still @todo.
4. I liked it as well, but it's not compatible with the form ID whitelist approach so I had to remove that.
5. Correct :)
P.S. Note that #2983266: Add PRESAVE and PREDELETE config events is already linked to this issue ;)
Comment #29
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThe fails from #27 reminded me that the entity storage wraps any exception with
EntityStorageException
, so there's no point in throwing our own exception class.Also fixed #26.3.
Comment #30
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedIn the meantime, I learned how to use expected exceptions properly :)
Comment #32
effulgentsia CreditAttribution: effulgentsia at Acquia commentedReally? What do you envision as the non-temporary solution?
Comment #33
Wim Leers#27:
If this is meant to be temporary as #27 says, then:
alterDeprecated()
instead ofalter()
:)Oops! 🙈😅 Sorry — missed that!
#29: OMG 😱 However … we can call
EntityStorageException::getPrevious()
to still get the workspace exception, right? At that point there's less value in doing so of course.#30++
+1 to this question.
Comment #34
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@effulgentsia, I assume that converting path aliases to entities, adding support for config and converting most core entity types to revisionable and publishable would cover most of the cases that need the "protection" added by this patch.
However, we're not there yet so let's go ahead and make these hooks official, we can always deprecate them later if we get to a point when they're no longer needed.
@Wim Leers, yep, having to call
EntityStorageException::getPrevious()
just in case the previous exception is coming from the workspace module kind of defeats the purpose.The initial test fail for #30 was a random fail in a quick edit test, so back to NR.
Comment #35
Wim LeersThat makes sense.
I manually tested this patch:
/admin/content
)This resulted in:
So, two UX refinements are needed.
Comment #36
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedA bit of manual testing is exactly what we needed at this point!
Re #35:
2. We can fix this situation by making out whitelist matching a bit smarter.
3. The error message comes from the comment form, since comments are not revisionable, and it shows why we can't display the error message before the form validation step: it would basically show up on every page which includes a comment form. So I reverted that change from #27 so we're back to displaying only a validation error after the user actually tries to submit the form.
Comment #37
Wim Leers:)
Wouldn't
views_form_*
be more in line with what people expect, i.e. "globbing syntax"?Also: either way (current implementation or proposed globbing syntax), this is missing an update to the docs in
workspace.api.php
.😢 I'm trying to think of a clever work-around here … I can think of three strategies (the top one being my favorite):
$form
with a weight of -1000000 so that it sits at the top._form
entry in the route definition that becomes the controller.Comment #38
effulgentsia CreditAttribution: effulgentsia at Acquia commentedI don't think basing the whitelist decision by form ID is enough. For example, a VBO form might be safe for supported entity types, like nodes, but not for unsupported ones, like comments. Similarly, there might be base forms that are workspace-safe, but child forms that extend that base form that have a submit handler that isn't workspace-safe.
The first thing that comes to my mind is that we should simply let any of the form build/alter/process functions set something like
$form['#workspace_safe'] = TRUE
. However, what I don't like about that is:So another possibility is perhaps to introduce a new service, like
workspace.form_validator
? And have it implement a method likeformIsSafe($form, $form_state)
orallowForm($form, $form_state)
? The implementation of the method could then set some internal property on $form or $form_state, or set it within a protected property keyed by the form's build ID, or whatever else seems good.If we go that route, I also think that the
formAlter()
andvalidateForm()
should live in that service too, at least for non-entity forms. So thatEntityOperations
only acts on entities / entity forms.Comment #39
effulgentsia CreditAttribution: effulgentsia at Acquia commentedI think it's fine for this issue to do it during the validation step. Let's open a followup (not beta-blocker, possibly stable-blocker) for informing the user earlier.
Comment #40
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@effulgentsia, I also didn't really like the form ID whitelist and I think your proposal is excellent! Implemented it in the patch attached.
Also opened #2985528: Inform users that they are not able to submit some forms in non-default workspaces before the form validation step as a followup to discuss/implement a better UX for this form protection and inform the user earlier.
Comment #42
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedWe need to bring back the beloved
WorkspaceFormInterface
so we can reliably detect our own forms.Comment #43
Wim Leers#38:
Very good point! 👌
HAH!
#39: Hm. Why can't this work?
#40:
To me, as a non-expert in the Workspace module, these look very similar yet are clearly used in different ways. I found this pretty confusing. Documentation explaining why we need
::isEntityTypeSafeToEdit()
andworkspace_entity_type_whitelist()
would be very helpful.Sorry for not raising this sooner :( It's only now that I realize this.
Wouldn't it be clearer if this were an entity type annotation, like
workspace_unaffected = TRUE
?Each entity type knows this best for itself, this removes the need for adding a new hook to our API surface (and for modules to implement another hook). And if a particular site needs to change this, they can still alter the entity type annotation.
Comment #44
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRe #43:
1. and 2. The purpose of the
isEntityTypeSafeToEdit()
method and the alter hook was to allow people to specify a list of entity types for which CRUD operations are allowed in a non-default workspace, and I wrote them as a "fix" for #24.1, but it's actually something that is not really required for this issue and can be implemented thoughtfully in a followup.What we actually need there is to allow CRUD operations in non-default workspaces for the entity types defined by the workspace module, especially
workspace_association
.Depends on what you mean by "disabling" the form :)
This can easily lead to situations like we had with core's search form before adding it to an allowed "whitelist", see the second screenshot from #2.
This could work I guess, but I would prefer to keep the scope of this issue as the "minimal amount of work needed to prevent leaking stuff to the Live workspace", and move the discussion about UX improvements to #2985528: Inform users that they are not able to submit some forms in non-default workspaces before the form validation step (which was also linked to this issue) :)
Comment #45
Wim LeersI much prefer #44 over previous patches since it's no longer introducing an API that seems to be of questionable and temporary nature. 👍
Just one last thing then now:
At this point, why not also just hardcode these form IDs? I'm asking because it seems this interface also is of a temporary nature? Asked differently: why isn't this also in the scope of #2985528: Inform users that they are not able to submit some forms in non-default workspaces before the form validation step?
P.S.: out of curiosity, why did you remove #2985528: Inform users that they are not able to submit some forms in non-default workspaces before the form validation step as a related issue?
Comment #46
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented@Wim Leers, I didn't hardcode the workspace form IDs because they vary by operation, see
\Drupal\Core\Entity\EntityForm::getFormId()
and bringing back the interface seemed simpler than doing regex tricks :)This change is in the scope of this issue because we need to allow access to all of the workspace-related actions:
WorkspaceActivateForm
,WorkspaceDeployForm
,WorkspaceSwitcherForm
, etc.And I removed the related issue because it's already linked the other way around, see the last parenthesis from #44 :)
Comment #47
Wim LeersI manually tested again. Works as expected. Comes with explicit test coverage. 👍
There are several things I still don't like about this patch, but they're not the fault of the Workspace module or this issue:
That being said: I'd prefer to see
WorkspaceFormInterface
be marked@internal
. The code doing the form alterations is marked@internal
— great! I don't think it makes sense to hold up this patch on that minute detail though, because there is still time to mark it@internal
during alpha, and hopefully #2985528 will get rid of it long before it ships with 8.6.0 :).All in all, this seems like a solid step forward!
Comment #48
plachCan we move this common logic into a dedicated method?
(Unrelated/not a blocker) I'm wondering whether we should adopt the same approach we have in Content Moderation and invoke
$storage->createRevision()
fromworkspace_entity_prepare_form()
to support content translation properly. At least until we are able to make any module leveraging pending revision play well with the other ones.Won't this be ignored when button-level validation handlers are set? See
FormValidator::executeValidateHandlers()
.Why are we whitelisting Views forms? Wouldn't this allow to run bulk operations say on comments?
Can we move this check before computing the value of
$workspace_safe
? It looks a bit weird that we perform all those checks and then throw them away if they aren't needed. Of course this is not a big deal performance-wise but still caught my eye :)Not wrapping at column 80 :)
(Unrelated/not a blocker) How come that commenting this line out doesn't make the test fail? Do we need more assertions?
It would be great if we could quickly add explicit tests for the path/book/menu validators, hopefully that's not too big of an effort.
Comment #49
plachAlso:
Would it make sense to make this alterable via PHP settings?
Comment #50
effulgentsia CreditAttribution: effulgentsia at Acquia commentedNeeds work for at least #48.3 and #48.4. IMO, the rest of #48 doesn't need to block commit, but if some/all of them are easy to address in a reroll, then great.
Re #49, I don't think so. Contrib can mark other forms safe via
$form_state->set('workspace_safe', TRUE)
. I think in a follow-up we should consider removing the search and views ones from the whitelist and make the search and views modules call$form_state->set('workspace_safe', TRUE)
from their form builders, but I don't know if we want to do that while workspace.module is experimental or wait till its stable.Re #48.3, great catch! One (but not the only) example of where that happens is the language edit form. So, if you enable language.module and then try to edit a language in a non-default worksapce, this patch's form validator doesn't run, but entityPresave() does, so you get an uncaught exception / "The website encountered an unexpected error. Please try again later." page. For now, perhaps all we need to do is iterate
$form['actions']
and add a button-level #validate to buttons that already have one, and open a follow-up to deal with that more robustly (perhaps as part of #2985528: Inform users that they are not able to submit some forms in non-default workspaces before the form validation step)? Unless someone has a better idea?For #48.4, I'd be fine with simply not whitelisting
ViewsForm
at all (disallowing any to be used within a non-default workspace) and opening a post-alpha followup for enabling the ones that are safe (like VBO on a supported entity type). Or do we know of existing Workspace use-cases that already rely on using VBO or other Views forms within a non-default workspace, and that we need to avoid regressing?Comment #51
plach+1 on every suggestion in #50.
I'd wait to set workspace safe flags outside the workspace codebase until it's clear this is the mechanism the stable version will rely on.
Comment #52
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedGreat review and suggestions!
Re #48:
1. My general rule is to move code to a dedicated method if it gets repeated at least 3 times, so this one doesn't qualify yet :)
2. I'm not sure about that, if this is the standard way of creating a new revision from an existing entity, should ContentEntityForm or Content Translation handle it automatically? In any way, I think it should be discussed more in a followup..
3. Awesome! Implemented @effulgentsia's suggestion, but applied to all actions because some of them might have specific submit handlers without having a validation handler as well.
4. I added ViewsForm to the whitelist when we were trying to display a message before the validation step, so I agree that we can remove it for now and think of a better way to do it. My initial impression is that this should be handled at the (VBO) action level, so we would automatically hide all actions that can not be performed in a non-default workspace.
5. Sure thing, done.
6. Oops :)
7. That test still passes because there is only one entity to match against, so all those conditions are specially crafted to look for the values of a single entity. The point of that test is to ensure that any kind of condition correctly selects the workspace-specific revision over the default one.
8. Those validators already have dedicated test coverage in
PathContentModerationTest
,BookContentModerationTest
andMenuUiContentModerationTest
and they will most likely disappear in Drupal 8.7, so I'm not sure adding even more test coverage for them is worth it..Comment #54
plach@amateescu, #52:
1: The choice of 3 seems rather arbitrary to me: the goal was isolating a standalone piece of logic, so the amount of times it appears doesn't really matter much to me, even one would be fine. Anyway, definitely not a blocker so I won't fight over this :)
2: Definitely a separate issue, but
::createRevision()
is already the new recommended way to create new revisions (surprise :)), especially after #2975754: Add hooks to act on a new revision being created has been committed. So I guess it could even be hardcoded in theContentEntityForm
itself.3:
I don't think doing this unconditionally is ok either: this code will cause any existing form-level validator to be skipped. On a second thought, I guess we should traverse the whole form array and detect any existing button-level validators and only ours in those cases. AAMOF
$form['actions']
might not be defined or not be the only place where button-level validators are defined. Setting status back to NW for this.4: Since this is still experimental, I guess I would be fine with any action being prevented in non-default workspaces. But you're welcome to come up with one of your magic tricks if it doesn't take long :)
8: We know that those validators work, but we have no guarantee that they are applied to Workspace: I was hoping a very quick addition to an existing test could cover that. Anyway, not a blocker if it takes too much time, again this is only experimental. However IMO we should at least add a @todo and create a follow-up to be addressed before stable, unless we are able to solve this entire problem-space properly before that, which I guess is unlikely.
Comment #55
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRe #54:
1. It's not really arbitrary: https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming). I thought you were a fan of Martin :)
2. I think this discussion goes way beyond forms TBH, because all the modules in the API-First ecosystem also need a clear way to handle revisions, including creating new ones. But we'll see about that when we'll get there.
3. Ohh, I totally missed @effulgentsia's point that a button-level validation will disable the form-level ones :/ Refactored the code to add our validator whenever needed.
4. I don't think I have magic trick here, but we could simply follow the same approach used in this patch for forms. I opened a followup issue to discuss/implement that: #2986005: Add the ability to mark (VBO) actions as workspace-safe
8. At least converting path aliases to entities and making menu links revisionable are some of the main goals of WI for 8.7, so I would say that it's very likely that the problem-space would be solved properly by the time Workspaces would be marked as stable.
Comment #56
plach1: I wouldn't call myself a fan, I just try to enrich my experience with that of people more knowledgeable than me, which doesn't imply I always agree with them. Anyway, I stand corrected on the "arbitrary" term, but I thought you had a protected method or two to spare ;)
3:
Won't this skip Workspace validation entirely, if no
#validate
key is defined at any level? I guess we should restore the form-level validator line.4: 👍
8: I hope we remember to add test coverage, shouldn't it happen.
Comment #57
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedI based the code on the assumption that every form gets a default
#validate
key added by\Drupal\Core\Form\FormBuilder::prepareForm()
..Comment #58
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedAbout #48.1, an additional reason for why I'm not fond of having a separate method for that line is that it would hard to come up with a name that wouldn't clash with the existing
WorkspaceManagerInterface::isEntityTypeSupported()
. See the previous discussion about theisEntityTypeSafeToEdit
method (which has been removed in the meantime), and @Wim Leers' feedback about it in #43.Comment #59
plachAh, ok, we should be good then: if some code is so evil to manually unset the
#validate
key, then it deserves some more manual work, I guess.Comment #62
effulgentsia CreditAttribution: effulgentsia at Acquia commentedThanks! Pushed to 8.7.x and 8.6.x.
Comment #63
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedFix component following module rename.