Problem/Motivation
This issue was originally created with the migration yml plugins in mind, it has been expanded to include all plugins. See #39.
Migrations are plugins and plugins are covered by the core BC policies, specifically :
Particular plugins, whether class based or yaml based, should not be considered part of the public API. References to plugin IDs and settings in default configuration can be relied upon however.
This means that in order to remove migration ymls from core, we must first deprecate them, and then remove them in the next major version. We currently have no means of marking migration ymls as deprecated nor triggering a deprecation error if they are used. This came up for the first time in #3022401: Remove useless config action.settings.recursion_limit where it was determined that the action_settings migration was no longer needed. The migration was set to a null destination to render it useless but there is currently no mechanism to declare it deprecated and scheduled for removal in Drupal 9.
We are now faced with the prospect of deprecating all the Drupal 6 migration for removal to a contrib project, and we have no means of marking them for removal in D9 either.
Proposed resolution
Add a Trait for checking the deprecation status of a plugin.
Indicate deprecation by the property 'deprecation_message' for a plugin defined by an array or 'deprecationMessage' for a plugin with an object definition. Adding a plugin flag was considered but was deemed redundant, the presence or absence of the message is sufficient.
Make it so other plugin systems in contrib can use this to deprecate as well.
Remaining tasks
Identify a list of relevant places that all need to be updated and create follow-up issues for that.
Update deprecation policy
User interface changes
none
API changes
A means to declare a migration as deprecated and trigger an error will be added
Data model changes
None
Release notes snippet
Core migrations can now declare themselves deprecated
| Comment | File | Size | Author |
|---|
Issue fork drupal-3039240
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
gábor hojtsyWhat about just adding a
deprecated: 1or something along those lines?
Comment #3
heddnAll migration yamls can be backed by a class. We could add such a class that has either in its constructor or somewhere a trigger_error, etc.
Comment #4
heddnDiscussed this in migrate meeting. Only want to trigger this on use, not necessarily on discovery. Perhaps add an interface with a method for the message. Then leave it up to the plugin managers or executors to figure out how/when to trigger the error. All of these would require adding a
classitem to the yml file.Comment #5
andypostAnother question is when we move plugins or migrations to other module - how to keep traces and "reparent"
Comment #6
gábor hojtsy#3064017: Create a means to mark an asset library as deprecated in a *.libraries.yml file should provide some prior art.
Comment #7
gábor hojtsyComment #9
quietone commentedReference policy issue
Comment #10
wim leersIt appears this is blocking #3096676: system_maintenance migrations uses incorrect maintenance mode variable in Drupal 7 migrations.
Comment #12
larowlan@quietone, @jibran, @xjm and I worked through this at DrupalSouth
Here's some WIP code as a discussion point
Comment #14
larowlanComment #15
andypostMaybe make this interface broader and allow use it for other plugins/managers?
It could be useful instead of #3094722: Add "no_ui = true" to the definition of deprecated action plugins
Comment #17
heddnIn Java, there's a Serializable interface. This is simply a marker interface that has no methods. In the case of this interface, we need to getDeprecationMessage method. But similar to Java, we don't really need this method, because any implementations of this interface are by definition deprecated...Doing that would obviate the need for the Trait. So less is more :)
OK, changing my opinion after reviewing the rest of this patch. Instead of adding an interface and trait, I highly suggest we put this on the base MigrationInterface (or even PluginInspectionInterface with implementation in Drupal\Component\Plugin\PluginBase). It is all about providing metadata about the plugin. And PluginInspectionInterface has as its docblock:
Plugin interface for providing some metadata inspectionHow much does this alternative break core? Let's see just for kicks and giggles. BTW, I think we are allowed to do this with BC from my reading of https://www.drupal.org/core/d8-bc-policy#interfaces
Comment #18
heddnWhoa, that's a lot of failures. Let's see if this results in fewer.
Comment #19
heddnComment #20
heddnSo the PoC passed green. What does that tell us?
Comment #21
andypostPresence of message is a signal to deprecation (plugin annotation property) so isEmpty($this->deprecationMessage) should be enough
Comment #22
heddnI had the same thought as #21.
And we might need the trait, but its for 2 places in all of core. I feel like we're probably OK without it. And we need to update the comments. But first, we need a comment from the plugin subsystem maintainers if we're going to go this route.
Comment #23
heddnRather then just waiting more weeks here, does anyone else have opinions about #12 vs #19?
Comment #24
quietone commentedI think I like the approach in #19 but can we add a example of deprecating a migration, like system_maintenance, as in #12?
Comment #25
andypostThe real need for that is #5
#3067299: Move actions migrations and tests to system module and #3022401: Remove useless config action.settings.recursion_limit
Which could be used as example
Comment #26
wim leersMigrations are plugins. All plugins may eventually need to be deprecated. So I think #19 makes more sense. I doubt that core committers will accept a new one-off kind of deprecation infrastructure.
The only way I could see #12 being favored is if it also works for non-plugin-based migrations, because then the "consistent for all plugins" argument disappears. Is that even a thing? IOW, does it even make sense to deprecate migration config entities?
Comment #27
damienmckennaRemoving the word "core" from the issue title as this is a general issue, not specific to core.
Comment #28
damienmckennaClarified the title further.
Comment #29
wim leersAs of #2746541-312: Migrate D6 and D7 node revision translations to D8.309.4, this is blocking #2746541. That issue is critical. Hence elevating this to critical too.
Comment #30
gábor hojtsyIt is not possible to introduce new deprecated APIs in Drupal 8/9. For new deprecated APIs for removal in Drupal 10, they are currently on hold and should be filed against Drupal 9.1 (see https://groups.drupal.org/node/535670). So unless super-critical to deprecate something, we should not blocking any Drupal 9 blockers with deprecations, as that would be a paradox.
Posted at #2746541-318: Migrate D6 and D7 node revision translations to D8 too.
Comment #31
mikelutzThis is tricky, we can't use the system to deprecate something until 9.1, and ideally we would deprecate something with this issue, so I'm postponing until 9.1, and dropping the priority. It sounds like this is going to head for a generalized yml plugin deprecation system, so this should probably get moved over to the plugin system rather than the migration system, but I'll leave it here for the moment.
Comment #32
heddnI'll move it over to the plugin subsystem.
Comment #33
quietone commentedI think this is no longer postponed.
Comment #34
andypostreroll for 9.1
Comment #35
heddnNW for adding tests and adding an implementation of this for action plugins.
Comment #36
benjifisherI am updating the "Remaining tasks" in the issue summary based on @heddn's comment.
Comment #37
quietone commentedI'm keen to work on this but don't where to start on the tests. Can someone layout the work in some detail, what tests to go where?
On the other hand. should we wait for a subsystem maintainer review before spending time on the tests?
Comment #38
jibran@quietone let's start by pinging any one of these folks in slack.
Comment #39
eclipsegc commentedOk, so having read up on this, a couple of quick observations:
Comment #40
heddnRe #39
1: +1 on a trait. We did have that back in #12
2: Yes, this should be for all types of deprecation. However, the specific plugins in migrate we are trying to deprecate are yaml based.
3: +1, We had that back in #12 as well.
4: Maybe, but that could/should be a follow-up, no?
Just to re-iterate. Doing it via discovery is not what we want. Because we want deprecated migrate plugins to be discovered. But only trigger_error on instance creation and execution.
Comment #41
eclipsegc commentedRe: 4
Yes, I think that would be a follow up. I just wanted to have the discussion and see how it impacts on ongoing use. It's important that we don't affect mainline discovery since instantiation leverages that same process, so you need to apply a filtering process for it. We actually already have a filtering mechanism in place for plugins leveraging contexts. I wonder if that system is generic enough to use here. As a general rule, leave Discovery alone. Messing with it tends to cascade into other problems.
As far as the trigger_error stuff goes, we should probably put that into a protected method on the trait and call that method in the constructor. Let's just make sure getting this functionality is as easy as possible for other Plugins in contrib that may not have used our base classes.
Eclipse
Comment #42
eclipsegc commentedSo, something more along the lines of the patch I've provided here.
However, after working with the code, there are a couple things more worth pointing out here.
Don't take my patch here TOO seriously for all the reasons mentioned above. These just came to me after I'd worked through the code a little. I do, however, want to see if it passes.
Eclipse
Comment #43
andypostNW for docs and tests
Having empty deprecation message could be confusing
maybe isDeprecated could be removed in favor of
!empty($this->deprecationMessage)Comment #44
deepak goyal commentedComment #45
deepak goyal commentedHi @andypost
Made changes as you suggested please review.
Comment #46
neclimdulIf we're going to replace the internal usage of the isDeprecated property, should you just replace it in the method as well? Seems like it would lead to the possibility of a weird state where something is "deprecated" in the flag but also not triggering and deprecation messages because the message is empty. Then we can just remove the property entirely.
Comment #47
eclipsegc commented@neclimdul This is precisely my point. The properties don't seem useful to me. Adding this data to the definition does seem useful. We can introduce handling into the plugin manager(s) (or base classes) to identify this and trigger_error() as appropriate.
Comment #48
neclimdulSo I grabbed EclipseGC on slack and after meandering around on a bunch of ideas and a few tangents we came back around to liking the InspectionInterface currently in the patch. It makes a lot of sense for a lot of use cases.
The implementation has lots of things to figure out though. Most crucially we agreed it needs to be more usable out of the box.
@deprecated = TRUEordeprecate: trueand this all starts working and each type doesn't have to create their own implementations to make things work. A key benefit to pushing this down to the definition is, as Eclipse has been trying to convince us, the plugin manager and other parts of the plugin system can act on it _without_ creating instances of the plugin which is clearly ideal. You could maybe ask your discovery for a list of deprecated plugins, or a list of not deprecated plugins, or upgrade tools could poll plugin managers and provide reports based only on definitions. This doesn't force the implementations but allows for them.Note: I understand why migrations don't want to trigger on creation as noted in with #3. migrate often needs to instantiate plugins to do things like run a requirements check and triggering deprecation outside actual use would lead to problems and confusion. I think this is actually still inline because you can replace the triggers logic as its implemented now we just need to be mindful of this around any trigger logic.
Comment #49
heddnIt isn't clear what the next steps should be. Are we still in a deciding phase or just need to re-roll the latest patch with some tweaks?
Comment #51
quietone commented@heddd, I'm not sure either but I decided to make changes for #48 in the hopes of moving this along.
#48.1 Removed the properties and used a definition key of, 'deprecationMessage' to determine if the plugin is deprecated. Is that what was intended? If so, where does 'deprecationMessage' get documented?
#48.3 Yes, compute isDeprecated. Keep it simple, the extra clutter in the plugin isn't needed.
For myself, I prefer this
deprecation_message: 'Deprecated in 9.2.x ...'to this
in a migration yml.
Which brings up a final point is it 'deprecationMessage' or 'deprecation_message' or both?
Comment #52
quietone commentedLet try that again, checking if the plugindefinition is an array.
Comment #53
tim.plunkettThis raises an interesting point: what about instances of PluginDefinitionInterface? (aka EntityType, Layout, SectionStorage)
Comment #54
joachim commentedWe have some duplication here: #2922451: [policy no patch] Make it possible to mark plugins as deprecated
Comment #55
wim leers#54: @quietone already linked that in #9 😊
Comment #56
quietone commentedAnd now something for #53.
Comment #59
joachim commentedLooks good! I spotted a docs error:
This says migration in the base plugin system.
Comment #60
quietone commentedChanged the test a bit and the comments for #59.
Comment #61
quietone commentedTried to bring the IS up to date.
Comment #62
quietone commentedLets see what this looks like when deprecating a migration plugin. I added #3096676: system_maintenance migrations uses incorrect maintenance mode variable in Drupal 7 migrations which deprecates system_maintenance.yml, I used that one because the patch is smaller than the one for the action plugin, #3067299: Move actions migrations and tests to system module.
The changes here are:
Comment #64
quietone commentedI don't know how to prevent the tests from complaining about the deprecated plugin that is created in the tests. Is this the right approach for migrate anyway?
Comment #65
quietone commentedI just rewrote #3096676: system_maintenance migrations uses incorrect maintenance mode variable in Drupal 7 migrations so deprecating migrations can be avoided so should change to using the action plugin issue as an example. In the meantime it would be good to get some feedback on this.
Changing to NR to get feedback on the approach here, particularly for deprecating migration ymls.
Comment #66
heddnFor #62.1: which tests are triggering on creation? Is it tests or is it something else like "find all the plugins" (discovery), then go out and create them (creation). If it is this, when we would need some way to filter out deprecated plugins that are not in use before creation. How do we know if a plugin is in use? For migrate in core, we would always want to filter out deprecated, because core shouldn't use them. The tricky part for that statement is running incremental migrations. In that case, I'd argue we still want to filter out deprecated plugins. But someone else might argue the opposite. And if we are always filtering out during discovery, we aren't really "deprecating".
For contrib where migrations are "cloned", we would want to trigger error if we create any cloned/deprecated migration. But we wouldn't really have a "deprecated" migration if it is yaml. As these are place in time copies and no one would copy over a deprecated yaml. That would be crazy.
So, I'm back to, we need to find some step in the process for triggering error on creation. And still don't have any clue what should be the trigger 🤔 or even if we should filter.
Comment #67
xjmComment #68
quietone commentedJust a reroll.
Comment #69
quietone commentedTry again
Comment #71
daffie commentedPatch looks good!
Could we change the message to something more descriptive. When you do something wrong and you get the deprecation message "foo", you have no idea were is comes from.
We can change the code to:
return (bool) $this->getDeprecationMessage();.Do you get testbot failures, when you remove this change?
Comment #72
quietone commented@daffie, good to know this is going in the right direction.
This patch has fixes for the test failures in #69. Although I don't see why the change to SubProcessTest is needed, not sure why the fix works.
#71
1. A more realistic message is now in the migration yml. I presume there needs to be discussion on the format of that message?
2. Fixed.
3. With the suggested change the SubProcessTest still fails.
Comment #74
quietone commentedAh, I forgot I was filtering SubProcessTest and didn't realize other methods were failing.
Apply the same fix to testNotFoudnSubProcess as was done in testSubProcess.
Comment #76
quietone commentedBad patch, Ignore #74.
Comment #77
daffie commentedI think these need to be changed.My mistake, these are used with mocks and not the new deprecated test plugin.Comment #78
daffie commentedThe patch looks good to me and is RTBC.
We are creating new functionality in that plugins can now be deprecated, for that we need a CR.
Comment #79
quietone commented@daffie, thanks.
I started the CR but feel like I don't know enough about what it should contain. It is rather brief. What else is needed (besides someone with better written English skills)?
Comment #80
daffie commentedCould we add testing for when the plugin is in a class and has the property 'deprecationMessage' with the deprecation message.
Comment #81
quietone commentedYes, that should be done. Thanks for the reminder.
I wasn't sure what class to use but picked Layout from the list in #53. Not knowing anything about Layout this was an interesting journey and could be completely wrong. One good this is that it exposed an error in PluginInspectionTrait, where it was testing for PluginBase instead of PluginDefintionInterface. I found that during debugging and then found the same sort of logic in \Drupal\Component\Plugin\Factory\DefaultFactory::getPluginClass which is an encouraging sign.
Comment #83
quietone commentedChange getDeprecationMessage to not use get and adjust the deprecation test.
Comment #85
joachim commentedThe CR looks good to me!
Though I wonder about also recommending that a deprecated class plugin add something in its docblock about being deprecated. It seems to me that the $deprecationMessage property is something that could be overlooked by a developer. That would have been one advantage of having a flag in the plugin annotation -- it's easier to spot.
Comment #86
quietone commentedI do not know how to fix this nor am I confident the test is correct. I found LayoutTest so used that, adding a net template with a deprecation message, but the property name is deprecationMessage which seems wrong in a yml file. And then when the plugin is created deprecationMessage is in an array 'additional'. Don't know why or where that is happening.
Comment #87
benjifisherWe discussed this issue on slack a couple of weeks ago. Here are some of my comments.
From the proposed resolution in the IS:
Does "defined by an array" mean the same thing as defined by YAML?
If I read the test results correctly, then there are two problems:
I think this explains where the
additionalcomes from: (core/lib/Drupal/Core/Layout/LayoutDefinition.php, Lines 179-187):Do you have any idea where the other deprecation messages come from? Have you tried removing the deprecation message from the test
layout_deprecatedto see what happens?Comment #88
quietone commentedWell, since deprecateMessage is not a defined property we should test for it in additional. This changes getDeprecationMessage to do that. Also changed the property name in the yaml to be consistent with practice.
Comment #90
andypostif ($this->pluginDefinition->deprecationMessage ?? NULL)the?? NULLis not neededComment #91
kishor_kolekar commentedHey, I have tried to cover the points mentioned in #90
Please review
Comment #92
quietone commentedThat changes causes an
Undefined property: Drupal\KernelTests\Core\Plugin\Context\TestPluginDefinition::$deprecationMessageerror so I'm ignoring the patch in #90.@kishor_kolekar, it is always worth running tests, at least the ones that are changed in the patch, before uploading for the testbot to test. The Drupal wiki has instructions for setting up and running tests locally. It does use resources, including money, to run the tests so we try to do what we can locally first.
This patch moves the test from PluginBaseTest to a new file core/tests/Drupal/Tests/Component/Plugin/PluginInspectionTraitTest.php and some tweaks to the trait to handle the 'additional' property used by Layout Plugins. Although, I am not sure if that should be in the trait or in the LayoutPluginManager.
Comment #93
quietone commentedI forgot to run commit-code-check so aborted the tests and there was a one line naming error. Let's try again.
edit: s/abort/aborted/
Comment #95
benjifisher@quietone:
You added the deprecated layout to an existing test module. That module is enabled by one of the functional tests, and that test ends up generating deprecation messages.
I think the simplest fix is to move the deprecated layout to a new test module. That fits with the general rule of not modifying existing tests unless you need to.
Comment #96
quietone commentedI am thinking the same thing but it was too late that day to act upon that. This makes a new test for testing a deprecate layout plugin.
Comment #97
andypostPolishing new methods and docs a bit, also few clean-ups for review bellow
I think it should return TRUE only when message is string
dispatcher should be used from contracts
Comment #99
andypostAnother attempt and fix
Comment #100
quietone commentedWhat action, if any, should be taken if the deprecation message is not a string?
Comment #101
andypostI see no way except
nullwhen no deprecation message defined, that's why I used to try applyis_null()Comment #102
andypostA bit more clean-up
- revert to
is_null()check because if plugin definesdeprecationMessagepublic property as not a string but then?stringwill throw on non string (otherwisetrigger_error()will fail fatal)- I see no reason to extend API of
MigrationPluginManageras the only place where filtering used (comment could be improved)It looks mostly ready, just not clear why
$plugin->deprecationMessagepublic property needed (maybe for typed data)Comment #103
xjmJust a small nitpick: Typically, we only use full words for variable names (so
$messagerather than$msg).Is this still in the patch?
Comment #104
andypostFixed #103 about naming, the property looks useless
Yes, it is used only in
getDeprecationMessage()and in testComment #106
larowlan->at() is deprecated, so we should avoid adding new calls if possible - there's a fair bit of existing usage here so probably not worth changing in this issue unless someone feels inclined - see #3217717: Replace usages of the at() matcher, which is deprecated
I'm wondering why we trigger in both the executable and the migration plugin manager.
Is there a supported way to create a Migration without using the plugin manager?
Comment #107
quietone commented106.1. Agree that, in this case, to add at() and remove in the #3217717: Replace usages of the at() matcher, which is deprecated
106.2. Yes, it is happening twice. Adding this to be discussed at the next migrate meeting.
Comment #108
quietone commentedWell, #3217717: Replace usages of the at() matcher, which is deprecated was committed, so re-rolling.
Comment #109
daffie commentedPatch looks good:
Can we replace this code with:
The helper method checkDeprecation() can then be removed. It is only used here.
Why is the PluginInspectionTrait included here? I am probably missing the point and there is a very good reason why. Could you explain?
We are now developing for D9.3 not D9.2.
Could you tell me which deprecation message test belongs to each trigger_error()? I want to be sure that both have testing.
Can we change the deprecation message to something more realistic.
Can we change this message to something more specific for this test. I just want to make sure that the message that we are testing is from this test class and not some other 'foo' message.
Comment #110
tim.plunkettI turned the patch from #108 into a MR.
#109
1) However unlikely, a plugin could opt to implement
PluginInspectionInterfaceand not extend from PluginBase, so I think it's appropriate to keep the method in the trait.2) ...and this proves my point from above. TypedData implements PluginInspectionInterface but does not extend from PluginBase.
3) Fixed
4)
MigrateExecutableTest::testMigrationDeprecation()testsMigrateExecutableMigrationPluginManagerTest::testMigrationDeprecation()testsMigrationPluginManager5) Fixed
6) Fixed
I also restored the
$pluginIdand$pluginDefinitionproperties to PluginBase. They are not necessarily used by other code (like TypedData). To preserve the expectations of PluginInspectionTrait, I added abstract methods for each of the corresponding methods.Untagging for subsystem maintainer review.
Comment #112
tim.plunkettI think this needs one more test scenario: An actual annotated layout plugin in
layout_deprecation_testthat declares itself deprecated via the annotation.Comment #113
tim.plunkettFixing credit
Comment #114
tim.plunkettAlso needs a case for a deprecated TypedData plugin, cause I think that's broken right now.
Comment #115
berdirWe also have the real-world use case of the NodeType condition plugin and we can convert the mechanisms around that (e.g. dynamically showing it only if it has existing configuration) to verify this.
Comment #116
tim.plunkettGood call! Switched NodeType to using this mechanism. I guess there's more to see about whatever hiding mechanism you're referring to...
When I add a call to
$this->checkDeprecation()toTypedData::__construct(), I get this error when trying to save a config entity (for example):Comment #117
tim.plunkettI found the other part of code @Berdir was referring to. Fixed that up.
Comment #119
quietone commentedFollow up made, #3252702: Add filter for un-deprecated plugins to PluginManagerInterface.
I am not sure what to do about the @todo mention Berdir. I'd prefer a follow up issue but is removing the @todo in scope here?
Comment #120
quietone commentedComment #121
quietone commentedI've made the test for the layout plugin and it seems to working fine. Typed data is completely different and I've yet to see the light.
I am not able to push changes so will make a patch in a day or so.
Comment #122
quietone commentedRemoving the 'needs tests' tag.
This does need a rebase but I still haven't figured out how to do that. The instructions do not work for me.
Comment #123
quietone commentedTests are passing, setting to NR
Comment #124
joachim commentedLooks good, just one nitpick:
Weirdly named test methods, especially when one is for YAML and one for annotation plugins.
Would make more sense to call them testLayoutDeprecationYaml and testLayoutDeprecationAnnotation. (And then as a bonus, you can run both tests together with '--filter=testLayoutDeprecation')
Comment #125
bbralaI might be missing something, but it feels like the
checkDeprecationmethod should be used more. This would mean it checks the message and print a deprecation error right away it seems. Why would we need the checks and trigger_error in the plugin themselves?I might be missing something here, but this confuses me.
Comment #126
bbralaAlso since the PR was updated to 9.4, this means the deprecation messages might need updating, since we are now targeting 9.4. This might also make removal in 10 a little harder, but i've heards of more deprecations that deprecate in 9.4 then removed in 10. Might need a release manager review though.
Comment #127
berdirFor the tests it doesn't matter, there is no BC for that, it's just for test purposes, but we should then probably actually use fake/placeholder numbers instead. And NodeType is already deprecated for 9.3, we're just moving that around, so I think that part is fine.
Comment #128
bbralaAh that is a good point, that makes things less complicated then :)
Comment #129
andypostIt's a blocker for #3204511: Deprecate tracker migration
Comment #131
xjmComment #132
quietone commentedUpdating this to D10.1. There were too many conflicts with a rebase so I applied the diff to 10.1.
Comment #133
wim leersSo this works generically, for all plugin types 👍
… so then why is this necessary? 🤔 I know TypedData has extra complexity. But how do we convey clearly in the change record which plugin types need extra attention?
👍 This proves it works generically.
Comment #135
joachim commentedI've done a proper rebase and a new MR for 10.1, leaving the 9.4 MR for the benefit of people wanting to patch their sites.
Please don't do squash merges just because conflicts are hard to resolve -- it means we lose the history of the work done on this issue, which makes it harder to understand the changes and to revert any of them in further work on this issue. It also makes it harder for a future rebase, if this issue needs to be rebased for 10.2 and so on. Rebasing a branch with a string of small commits is always easier than rebasing a single big commit.
The correct way to do a rebase to a different core branch is with the '--onto' option, like this:
First, get the issue branch up to date with its existing core branch.
1. Determine the core branch that the feature branch is against. e.g. 9.4.x.
2. Switch to 9.4.x. Git pull to get it up to date.
3. Switch to 1234-my-issue.
4. git rebase 9.4.x. Resolve any conflicts.
5. git push -f
Now, we rebase onto the new core branch, e.g. 10.1.x:
1. git checkout --track origin/10.1.x or `git checkout 10.1.x`
2. git pull
3. Switch to issue branch: git checkout 1234-my-issue
4. Make a new issue branch. This is so that people can continue to use the old issue branch if they are using an older version of Drupal: git checkout -b 1234-10.1-my-issue
5. Now we take the new issue branch, snip it from 9.4.x, and stick it onto the tip of 10.1.x: git rebase --onto 10.1.x 9.4.x. Resolve any conflicts
6. Push the branch and make a new MR.
There were only two conflicts:
- a change to the NodeType condition which has since been removed from core
- a conflict in BlockForm due to the same
Setting to NW because this doesn't look right:
Consumers of plugins shouldn't need to know specifics about which plugins are deprecated. All deprecated plugins should be handled correctly -- and that should probably happen at the plugin manager level rather than in the form class?
Comment #136
berdir> Consumers of plugins shouldn't need to know specifics about which plugins are deprecated. All deprecated plugins should be handled correctly -- and that should probably happen at the plugin manager level rather than in the form class?
A deprecated plugin can still be used, and if and when it it is shown and how that message is presented is up to the specific implementation, that can't be generalized. As this example shows, we want to show a deprecated plugin only if it's already in use, so it depends on existing configuration, which is not something the plugin manager has knowledge of. At best the first part could be a method or something to make it a bit more readable.
Comment #137
tart0As deprecated plugin can still be used, yes.
Why couldn't we still use PHP Annotations ?
Comment #138
joachim commented> As this example shows, we want to show a deprecated plugin only if it's already in use, so it depends on existing configuration, which is not something the plugin manager has knowledge of.
Agreed, but making the code specific to the NodeType plugin is wrong here. What if a contrib module was providing the FooBar condition plugin, and then deprecated it?
Comment #139
berdirThat's just the restored comment from the old node type specific logic that used to be in that place in D9:
that was dropped including the todo in D10. That's the leftover from merging/rebasing that.
the code is not actually specific about that, so we just need to fix the comment. That said, BlockForm is full of hardcoded customizations for specific core plugins that look different on block visibility conditions than elsewhere.
Comment #140
andypostConsumers should know, cos something needs to apply "no_ui filtering" like #3094722: Add "no_ui = true" to the definition of deprecated action plugins
Comment #141
quietone commentedI think the changes to BlockForm are out of scope for this issue. That change is deciding what to do when a condition plugin is deprecated in the case of Blocks whereas the scope here is simply to create a way to declare a plugin as deprecated. But I could be wrong - I have been doing a lot of that lately.
edit: fix formatting of 'what'
Comment #142
berdirIt can go either way. For Drupal 9, since this dealt with the specific one-off deprecation of the NodeType condition plugin, updating BlockForm had to be included. In Drupal 10, that's gone, so we can leave it out. That does however mean that it won't be able to handle a deprecated condition plugin from a contrib module for example. But then again, the same can be said about all other UI's that list all possible plugins somewhere: The add block list for example if you deprecate a block plugin, or the actions module when deprecating an action plugin and so on. So to get this in, we probably need to identify a list of relevant places that all need to be updated and create follow-up issues for that. They might all need fake-deprecation in test modules to be able to test it, so that is going to be a bit of work.
Comment #143
andypostneeds work for version independenct message in test, otherwise looks ready
Probably it backportable to 9.4.x but current MR for 10.1.x and 9.5 could be needed for porting, ++ #142 and other "no ui" patches could go as follow-up
Comment #144
quietone commentedI have updated the CR.
What are the places that need followup?
Comment #146
quietone commentedI made changes for the latest unresolved issues. There is an MR for 9.5 (which does still have the changes for NodeType condition plugin) and 10 and both are passing tests. Back to NR
Comment #147
joachim commented> What are the places that need followup?
Menu plugins will need not just a deprecation message, but a way of indicating the replacement plugin.
Use case: node module wants to rename some of the menu/task/action plugins it defines for nodes (see #2976861: add an entity Links handler, to provide menu links/tasks/actions for entity types for reasons). But contrib and custom code refers to the deprecated task plugins, for example as parent items.
So node module needs to be able to tell the menu system, 'Plugin X is deprecated, anything that refers to plugin X should actually get the replacement, plugin Y'.
Comment #148
joachim commentedOops, edit conflict, didn't mean to change the status!
Comment #149
smustgrave commentedSkimmed.
But seems to be a failure in the MR 2821 for D10.
Comment #150
andypostrebased, failure looks unrelated
Comment #151
smustgrave commentedThis seems like a big change.
The 2 open threads seem to be resolved as @quietone changed to "some deprecation message"
The two remaining tasks
Have those been completed?
Comment #152
smustgrave commentedFor the 2 remaining tasks if they can be identified.
Comment #154
heddnWe have some old layouts (in my_module.layouts.yml) that we want to deprecate and use a more general use case layout instead. It would be nice to make the IS more explicit that this will cover those yaml plugins as well.
Comment #155
joachim commentedThe CR has an example of deprecating a YAML plugin.
But the CR leaves a lot unsaid and is confusing in other ways:
> Methods are added to check for the deprecation when a plugin is constructed, to determine if a plugin is deprecated and to get the deprecation messaged.
Whose responsibility is it to check for a plugin being deprecated? Will core's plugin managers take care of checking their plugins, or is it up to the code that gets a plugin instance?
Comment #157
andypostCreated new MR for meaningful 7 commits against 11.x branch by cherry-picking and fixed PHP 8.3 compatibility in test
ATM mostly migration plugins awaiting this deprecation
Also attributes conversion may need it #3265945: Deprecate plugins using annotations and plugin types not supporting attributes
RE #151
at least 2 blocked
- #3204511: Deprecate tracker migration
- #3209220: Deprecate and remove action settings migration
updates has policy issue #2922451: [policy no patch] Make it possible to mark plugins as deprecated
PS: probably makes sense to file follow-up to introduce
#Deprecatedattribute like https://wiki.php.net/rfc/deprecated_attribute but for classesComment #158
andypostAttempt to use the current code for migration https://git.drupalcode.org/project/drupal/-/merge_requests/6075
Comment #163
smustgrave commentedLeft some small comments.
Hid the old branches for clarity.
Comment #164
andypostrebased and addressed feedback
Comment #165
smustgrave commentedFeedback appears to be addressed! Thanks!
Comment #166
berdirThis seems to only add support for annotations and it relies on undocumented, undefined annotation properties to do so.
We need to make sure this works on attributes as well, which in its current state, I believe it does not, because for example the just committed Mail attribute class in #3420977: Convert Mail plugin discovery to attributes has a fixed, hardcoded set of properties defined in its constructor and it is not possible to just pass in additional stuff the way this expects it to.
I think we need to do either or both of:
a) Standardize on using ...$var to pass all extra constructor arguments through to the parent. See for example ConfigEntityBase in #3396166: Convert entity type discovery to PHP attributes, so that the attribute base class can introduce and define the deprecated_message property and it works an all child classes too.
b) Support an explicit additional key, which is considered here in the trait in the parent class, so that extra stuff can be put there. We discussed that a bit in the original issue but postponed its introduction on having use cases for it, more or less defining that it would be done for specific plugin types that are likely to be extended.
Comment #167
longwaveI agree with #166. While PluginDefinition declares AllowDynamicProperties we should not be relying on that for deprecations and should be introducing specific properties, and I think AttributeBase and AnnotationBase also need properties and setters adding to match.
To me option A from #166 seems simpler, as it means we have to explicitly declare all our properties and we will not be tempted just to dump extra keys into the "additional" property unless absolutely necessary (e.g. in the case of entity types, at least to start with).
I also tried prototyping a separate attribute, e.g.
but this doesn't really seem to gain us much - static analysis could find all deprecated things more easily if they all shared one attribute, but it complicates discovery as we have to check the second attribute and doesn't map well to YAML plugin definitions.
Comment #168
joachim commentedIs this going to be extensible by specific plugin types?
For example, in the menu system, we need to be able to not just say plugin 'foo' is deprecated, but to use plugin 'bar' *instead*.
Comment #169
longwave@joachim in a way that needs to be understood by code and handled automatically, or only in a message to be read by humans?
Comment #170
joachim commented> In a way that needs to be understood by code and handled automatically, or only in a message to be read by humans?
By code.
Suppose node module defines a menu link 'foo'. It wants to replace that with 'bar'.
Contrib and custom code declare their own menu link items and say 'parent: foo' because they want to place their pages within Node module's admin UI.
The menu system needs to be able to go 'Oh, I'm going to use 'bar' as a parent for that item instead because 'foo' is deprecated'.
The use case is #2976861: add an entity Links handler, to provide menu links/tasks/actions for entity types, where we need to deprecate hardcoded menu links/tasks/actions and replace then with automatically-created ones.
Comment #171
longwaveIn services this can be done with aliases; you create the new service and alias the old service name to it. Aliases can be deprecated too. Do we need this concept in plugins too?
Comment #172
berdirA specific plugin system can always define additional keys on top of this, like a replaced_by or something. For most other plugins that's likely not needed or more complex, as plugins usually have configuration and the configuration of the replacement might not apply 1:1 and so on. So I'm not sure if that we need to build this into the base functionality.
Comment #173
longwaveThe more I think about it the more I wonder what is a plugin manager, if not much more than a service container/locator that only contains a subset of services that conform to a specific interface?
Comment #174
berdir@longwave: Plugins aren't (single-instance) services. Every node you load is a plugin object, so are fields and blocks and so on.
Comment #175
joachim commented> A specific plugin system can always define additional keys on top of this, like a replaced_by or something. For most other plugins that's likely not needed or more complex
Agreed - this is not going to be needed for most plugin types. I just wanted to make sure it'll be possible to add that on top of what's being done here. This issue is the last blocker to the entity links handler issue :)
Comment #176
andypostMaybe better to address Attribute and "attribution-discovery" deprecations in follow-up as ATM core needs deprecation for annotation discovery
Additionally to #167 there's PHP RFC for the
#[Deprecated]attribute which has stuck- https://github.com/php/php-src/pull/11293
- https://wiki.php.net/rfc/deprecated_attribute
But PhpStorm has implementation which has growing adoption
- https://packagist.org/packages/jetbrains/phpstorm-attributes/stats
- https://github.com/JetBrains/phpstorm-attributes