Problem/Motivation

In #2916740: Add generic entity actions we want to mark some node and comment action plugins as deprecated and replace them with generic entity actions. Since #2870194: Ensure that process-isolated tests can use Symfony's PHPunit bridge to catch usages of deprecated code landed, it's no longer possible to mark the complete action plugin class as deprecated, because during tests, the plugin discovery will still call this class and trigger the deprecation error.

For example the NodeActionsConfigurationTest test opens up the UI and as part of that the deprecated plugin will be initialized.

So we need an other solution to mark plugins as deprecated.

Proposed resolution

I discussed this shortly with berdir and alexpott on IRC and a first proposal is to add a "deprecated" key into the plugin annotation and call trigger_error during Drupal\Component\Plugin\PluginManagerBase::createInstance()

Remaining tasks

Discuss
Implement
Review
Commit
Update https://www.drupal.org/core/deprecation

User interface changes

None

API changes

None

Data model changes

None

Comments

chr.fritsch created an issue. See original summary.

jibran’s picture

@EclipseGc shared some thoughts on this in #1932810-36: Add entity bundles condition plugin for entities with bundles

If we were to add a little logic to the default plugin manager, we could probably include a "deprecated = TRUE" in annotations and hide the plugin from being returned by getDefinitions() but still allow it to be instantiated. That would let us deprecate old plugin from the UI so that users aren't using it going forward and people can, over time unify on this plugin. We can then address anywhere core uses plugins for the 9.x migration when the time comes, or even add in extra logic to the ConditionManager that when "node_type" is requested, we instantiate "entity_bundle:node" instead. Something along these lines should be pretty doable.

chr.fritsch’s picture

I proposed in #2916740: Add generic entity actions another solution, which works without code changes. Why not letting the plugin manager implementing the FallbackPluginManagerInterface. getFallbackPluginId() will return the new plugin id's in case an old one is loaded. Then it's possible to remove the annotation from the old/deprecated plugin, which means the plugin discovery will no longer pick that plugin up.

EDIT: The only disadvantage is, that you will not be notified, that you are loading on old plugin id.

cilefen’s picture

catch’s picture

The ability to hide deprecated plugins in listings but still allow them to be used would be good for both Views and Field UIs.

Could we trigger_error() from methods that aren't used in discovery?

dawehner’s picture

Issue summary: View changes

Could we trigger_error() from methods that aren't used in discovery?

I was wondering for a second: Why are there just 4 test failures if the discovery is involved. It turns out, actually its stuff like the actual form which initializes the plugin. The actual code looks like this:

    foreach ($this->manager->getDefinitions() as $id => $definition) {
      if (is_subclass_of($definition['class'], '\Drupal\Core\Plugin\PluginFormInterface')) {
        $actions[$id] = $definition['label'];
      }
    }

Given that we could totally deprecate inside the constructor.

If we were to add a little logic to the default plugin manager, we could probably include a "deprecated = TRUE" in annotations and hide the plugin from being returned by getDefinitions() but still allow it to be instantiated. That would let us deprecate old plugin from the UI so that users aren't using it going forward and people can, over time unify on this plugin. We can then address anywhere core uses plugins for the 9.x migration when the time comes, or even add in extra logic to the ConditionManager that when "node_type" is requested, we instantiate "entity_bundle:node" instead. Something along these lines should be pretty doable.

The idea to hide deprecated plugins is a good idea! What about "simply" not add "deprecated = TRUE", but instead just "hidden = TRUE" and continue to use the constructor for the deprecation?

tim.plunkett’s picture

Component: base system » plugin system

I agree with keeping hidden = TRUE and deprecations separate.
Deprecations in the constructor also seems like the best option.

cilefen’s picture

Issue summary: View changes
catch’s picture

Agreed that's a good plan. Would also let us mark an entire module deprecated (to be moved to contrib or similar) but we might still allow it to be visible on sites it's already installed on including its plugins.

dawehner’s picture

@catch
Its special for action plugins, should we still treat all plugins different? It feels like every PHP class should better be deprecated via the constructor, as loading might happen at some point.

eclipsegc’s picture

FWIW, I think it'd be better to check the plugin definition during createInstance() in the DefaultPluginFactory for whether the plugin denotes that it's deprecated. Then if it is, we can do this trigger error stuff you all are talking about AND we get uniform support for plugin deprecation across most of core with one file change.

Eclipse

heddn’s picture

For what it's worth, I think the issue title should include deprecate in web UI. Or something like that. We've been deprecating quite successfully plugins in migrate for some time and not had issues. Either that an updated issue summary. Because I do not understand the issue then.

dawehner’s picture

@heddn
That is a good point. The fact that our traditional approach of deprecating any PHP class doesn't work is due to the action module doing something special. Given that I don't really like the approach in #11 / anything which is special to plugins.

berdir’s picture

I don't see how action.module is special here, conditions for e.g. block visibility have exactly the same problem, deprecating the code is one thing, but how do we tell the user which one he should use? See #1932810: Add entity bundles condition plugin for entities with bundles. My idea there was a combination of showing it with a (deprecated) suffix if it's in-use and not showing it at all when it's not currently enabled. But that is likely something that indeed each UI needs to do on its own.

About constructor vs factory, the problem with "one file change" is that there isn't one factory class.. There's DefaultFactory, ContainerFactory, ReflectionFactory (not sure if someone uses that, actually). What we could possibly do is put it in \Drupal\Component\Plugin\PluginBase::__construct() and check the plugin definition there, then we'd cover almost all plugins becaue they usually call the parent constructor.

eclipsegc’s picture

Putting it into PluginBase::__construct() is probably going to be about the same degree of successful as DefaultPluginManager::createInstance().

DefaultPluginManager::createInstance() doesn't ACTUALLY exist, it delegates to PluginManagerBase::createInstance(). What's important to point out is that all the classes you just named off are FactoryInterface implementing classes, NOT PluginManagerInterface implementing classes. The difference means that the PluginManager will actually get first shot at the plugin and that we don't have to change runtime code for every plugin we want to deprecate. I understand that, for some reason, dawehner doesn't like this suggestion. I do not understand why that is. I would like to since I have no way to address his concerns w/o understanding them.

What I DO know is that DefaultPluginManager is used by the vast vast majority of plugin types, both core and contrib, and that keying off the definition should allow us to limit whether a plugin is delivered by getDefinitions() or not (we'll have to write some code, but that seems doable). That said, I don't see why we want to alter (and or introduce) a constructor to every plugin we want to deprecate. Please let me know why we want to do this. Thanks!

Eclipse

claudiu.cristea’s picture

claudiu.cristea’s picture

#2921810-21: Allow TimestampFormatter to show as a fully cacheable time difference with JS shows that putting the deprecation error trigger in constructor doesn't help.

alexpott’s picture

@EclipseGc we want to do this because we want to deprecate plugins. And tell custom / contrib modules that are using them that they need to change something. I think adding the @trigger_error() seems sensible and adding it to the plugin file somewhere makes sense and the discussions above show why the constructor is a good choice.

@claudiu.cristea re #17 yes it did help. It told you that core was still using the deprecated plugin. In order to deprecate something you need to remove all usages.

I also think keeping the UI hiding as a separate thing makes sense too. Many plugins, for example field type and a plethora of views ones, use no_ui as a way of excluding a plugin from the UI. We could add a trait that gives discovery the ability to check the __constructor or class docblock for the @deprecated annotation and then exclude from the UI if the annotation has a no_ui key. Or we could just mandate that if you deprecate a plugin and there is a UI that you add the no_ui to the definition and then there's no magic. If there isn't a no_ui key for that plugin type then it will need to be added.

+1 to deprecating plugins by adding trigger_error() to the constructor.

catch’s picture

So the constructor deprecation attempt in #292181: Improved API documentation caused failures because several core views are still using the formatter, that's by design in this case, we just don't want to trigger deprecations during discovery.

Adding the deprecation to the constructor, even if it means adding a constructor seems like the best option to me, it should be the last change to the plugin anyway in most cases.

alexpott’s picture

Status: Active » Needs review

So given that @catch and I agree and plugin maintainer @tim.plunkett also agrees with constructor deprecation. I think we are good to go here but a +1 from the other plugin maintainer @EclipseGc would be also good.

alexpott’s picture

Here is the suggested update to https://www.drupal.org/core/deprecation

Plugins

Add @trigger_error('...', E_USER_DEPRECATED) to the plugin constructor. If the plugin does not have a constructor, add one. Add no_ui = true to the plugin definition. If the plugin does not support no_ui but is selectable in a UI then an issue will be needed to add it. Also, add an @deprecated phpdoc annotation to the plugin's class docblock. For example:

<?php

namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;

/**
 * Plugin implementation of the 'timestamp' formatter as time ago.
 *
 * @deprecated in Drupal 8.5.0, will be removed before Drupal 9.0.0. Use the
 *   \Drupal\Core\Field\Plugin\Field\FieldFormatter\TimestampFormatter formatter
 *   instead and configure it with "Display as 'time ago'" option.
 *
 * @FieldFormatter(
 *   id = "timestamp_ago",
 *   label = @Translation("Time ago (deprecated)"),
 *   field_types = {
 *     "timestamp",
 *     "created",
 *     "changed",
 *   },
 *   no_ui = true
 * )
 */
class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPluginInterface {

  /**
   * Constructs a TimestampAgoFormatter object.
   * ... rest of the docs ...
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, DateFormatterInterface $date_formatter, Request $request) {
    @trigger_error('\Drupal\Core\Field\Plugin\Field\FieldFormatter\TimestampAgoFormatter is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Field\Plugin\Field\FieldFormatter\TimestampFormatter instead. See https://www.drupal.org/node/2926275.', E_USER_DEPRECATED);
    // ... constructor code...
  }
berdir’s picture

The no_ui stuff is a bit tricky.

As mentioned in the block example, that flag must only be considered when creating something new with a plugin and/or there is no existing configuration because the current block UI has no concept of "adding" conditions, it simply lists them all and they might or might not have configuration already.

We should probably document the expected behavior for that clearly and I'm not sure if the existing no_ui implementions really cover that. I did a quick test by adding no_ui = TRUE to ImageItem and it still works for the existing fields and I can't add new ones, so basically it works as expected.

But I'm not 100% sure if that will be the same for other plugin types and if we should really re-use that flag for deprecations or instead introduce an explicit new property for this. But I guess we can also document that this needs to be decided per plugin type?

alexpott’s picture

@Berdir good point. I agree that a case-by-case basis is going to be best for the no_ui stuff. Tricky.

chr.fritsch’s picture

Since I opened this issue because we want to deprecate some action plugins in #2916740: Add generic entity actions, I applied the suggestion from #21 to the latest patch in #2916740: Add generic entity actions. We can see there, that this approach would work because we only have one failing test there currently. And that failure comes from the update path test. Which is ok for now because the update tests load the old plugins before running the update.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

Given @catch, @tim.plunkett and I agree that adding the @trigger_error() to the constructor is the best way forward I'm going to rtbc this. I think here we are agreeing a policy. There is no code change per-say that is necessary.

I agree with @Berdir that we should be careful with the no_ui part of the suggestion and use it only where it works and add good tests if we use.

catch’s picture

Yes +1, let's add the text from #21 to the deprecation policy then mark this fixed, we can revise as more comes up but this lets us actually do the deprecations elsewhere and doesn't require anything new to support.

chr.fritsch’s picture

I added the text from #21 to the deprecation policy.

See: https://www.drupal.org/core/deprecation#how-plugin

eclipsegc’s picture

Ok, it took a little bit to wrap my head around the approach here so let me start by saying I'm generally on-board and won't push back, but I don't like it. The rest of this post is my "why".

I don't like this because:

  1. The solution is designed exclusively for 1 edge case, manual instantiation of plugins. Frankly, no one should be doing this, and anyone who is is using the plugin system incorrectly.
  2. Adding code to a constructor isn't introspectable. We couldn't (for instance) introduce any sort of filtering mechanism that hides deprecated plugins from core's UI's.
  3. It also cannot be easily nuanced for situations where a plugin deriver might be involved. If, for instance, we have a plugin that depends on other plugins via a deriver and we deprecate one of the dependencies (think blocks wrapping fields and we deprecate a field) passing that deprecation knowledge along upstream is essentially impossible. YES the trigger warning will still eventually happen when the wrapping plugin invokes its dependency, but there's a whole layer of abstraction the developer will have to dig through to figure out how and why that warning is being triggered.

I realize that the idea of doing a no_ui in the plugin definitions is being considered a "separate thing" and I fully support that thing happening, however an @Deprecated('new thing', 'version', 'etc') annotation is introspectable, could contain the same sort of data we've established that we want here, and is ultimately a lot more robust. No, it doesn't cover the edge case of people manually instantiating plugins... but again I can't say that's considered a supported use of the plugin system and it should really only happen in tests if at all.

Eclipse

phenaproxima’s picture

The solution is designed exclusively for 1 edge case, manual instantiation of plugins.

Unless the plugin consists entirely of static methods, that's not true. All plugins are eventually instantiated under normal circumstances, either directly or via the static create() method. Am I missing something there?

eclipsegc’s picture

the developer shouldn't ever do new SomePluginClass(); they should be calling the plugin type's manager and invoking createInstance($plugin_id, $configuration); So there should always be a factory involved in the process.

Eclipse

phenaproxima’s picture

the developer shouldn't ever do new SomePluginClass(); they should be calling the plugin type's manager and invoking createInstance($plugin_id, $configuration)

Yes, but the factory will eventually do new Plugin(). Or the create() static factory method will. The constructor is guaranteed to run at some point. The plugin cannot be created any other way. Even doing it with reflection will call the constructor. The only way the constructor could be bypassed, as far as I know, is with PHPUnit's getMockBuilder()->disableOriginalConstructor() -- but that, as far as this issue is concerned, is an edge case.

eclipsegc’s picture

Let's back up. What I'm saying is that the solution outlined in this post is designed to work EVEN WHEN a developer manually calls the plugin's constructor. Manually calling the constructor via something like:

$plugin = new PluginClass();

This behavior by a developer is NOT SUPPORTED by the plugin system. The plugin system instead expects:

$plugin = $manager->createInstance($plugin_id, $configuration);

Yes, of course that will ultimately call the plugin's constructor. I'm not debating that. I'm saying the plugin system doesn't support developers manually calling the plugin's constructor, so designing for that misuse of the classes seems counterproductive to me given that the plugin system is essentially robust tooling for informing Drupal of aspects of these classes WITHOUT instantiating them. That's kind of the whole point of the plugin system, so deprecating plugins in this way, when it will do nothing to prevent the use of deprecated plugins (by say, hiding them in the UI) seems inefficient at the very least.

That being said, I'll expand on one other topic here. The use of "no_ui" in the plugin definition is, as I've previously said, something I completely support. That being said, I would posit that "no_ui" does NOT mean "deprecated". The inverse of this however may be true. Odds are "deprecated" always means "no_ui". All scotch is whiskey. All whiskey is NOT scotch.

Eclipse

berdir’s picture

One case where having it in the constructor over having it in the plugin definition/factory is possibly an advantage is when you have subclasses, if someone subclassed a plugin that is deprecated, then their plugin definition would not automatically be deprecated as well. But calling it will still trigger the deprecation message, which is kind of correct, because at the very least, that subclass will need to be updated to no longer depend on that deprecated class.

That said, I agree that also having it explicitly in the plugin definition could be useful, in a more explicit way than a no_ui flag. As explained in #22, the handling of deprecated plugins in the UI is not trivial. A plugin that is still being used and configured still needs to show up. You're just not allowed to add new ones and it will go away once all configuration is removed. But as I wrote, actually implementing that is most likely specific for each UI. But one thing that an explicit deprecated flag would allow us to do for example in the block condition/visibility UI is adding a (deprecated) flag behind them, maybe even strike them through or something like that.

eclipsegc’s picture

Yup, or hide them completely from being placed by the UIs but still let them be instantiated. That would let them continue to work, but prevent site builders from placing new ones. It could also give us a way to highlight pre-existing instances to which they need to give attention.

Eclipse

catch’s picture

What I'm saying is that the solution outlined in this post is designed to work EVEN WHEN a developer manually calls the plugin's constructor.

Just to say, this is a byproduct of the solution, it's not the reason the solution was chosen. The reason it was chosen was to trigger the deprecation notice only when the plugin is actually used and not when it's listed in UIs (which as has been discussed may be necessary to allow people to change the plugin used from the UI, but on a case-by-case basis).

however an @Deprecated('new thing', 'version', 'etc') annotation is introspectable

The proposed solution here includes adding @deprecated on the class, which is already introspectable. It doesn't preclude us adding an additional annotation key later if we decide to do that but the possibility is there to introspect @deprecated already.

The main thing for me here is that the solution here is closest to how we deprecated 'regular' classes/methods/functions - @deprecated and @trigger_error() in the thing being deprecated. There are cases where we'll have to add additional code to manage the deprecation process #2866779: Add a way to trigger_error() for deprecated hooks is the main example, but for me better to do that only when it's something we can't handle with @deprecated and @trigger_error() directly.

alexpott’s picture

+1 to #35 if we can stop deprecated plugins from being used in the UI that's great but the real purpose of deprecation is to allow developers / testing infra to know when deprecated code is being used.

eclipsegc’s picture

Yes, I understand that and am on board with it. That being said, with the current approach, how do you intend on dealing with things like derivatives?

Also, just a clarification, I was never suggesting that deprecation warnings should get thrown during a listing operation. The intent was always to do that during the factory's instantiation procedures. I think that was clear, but in case it was not, I thought I'd make it more so.

Eclipse

larowlan’s picture

Title: Make it possible to mark plugins as deprecated » [policy no patch] Make it possible to mark plugins as deprecated
Status: Reviewed & tested by the community » Needs review

Looks like there is more discussion to be had here?

Although the docs have already been updated...so maybe this should be marked fixed with a followup for the remaining concerns?

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

berdir’s picture

Status: Needs review » Needs work

In #1932810: Add entity bundles condition plugin for entities with bundles, we now have this snippet:

+++ b/core/modules/block/src/BlockForm.php
@@ -249,6 +249,15 @@ protected function buildVisibilityInterface(array $form, FormStateInterface $for
+
+      // Don't display the deprecated node type condition unless it has existing
+      // settings.
+      // @todo Make this more generic in
+      //   https://www.drupal.org/project/drupal/issues/2922451.
+      if ($condition_id == 'node_type' && !isset($visibility[$condition_id])) {
+        continue;
+      }
+

The goal is that BlockForm could apply the same logic to any condition plugin that declares itself as deprecated.

Right now, with the definition we have, that's not really possibly or only in a very complex way as I'd nee to parse the dockblock myself of the plugin class myself. Which might actually not work if for example ctools would alter the class of that plugin to something else (That is actually exactly what is happening right now)

IMHO, there are two options:

a) Our plugin discovery would automatically somehow detect the @deprecated and inline it into the plugin definition
b) We duplicate the @deprecated annotation into @Plugin and add that as an official thing to \Drupal\Component\Annotation\AnnotationBase

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

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

joachim’s picture

> add a "deprecated" key into the plugin annotation and call trigger_error during Drupal\Component\Plugin\PluginManagerBase::createInstance()

That only covers annotated class plugins.

Should we discuss YAML plugins here too, or fix the scope of this issue and file a new one for YAML plugins?

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

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

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

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

andypost’s picture

heddn’s picture

Seeing this is a policy, no patch issue... we should try to set policy that applies to *all* types of plugins. Or re-title this to only code based or UI based or something else based plugins. This is a blocker though for #3039240: Create a way to declare a plugin as deprecated, where we need to find a solution to yml based plugins.

joachim’s picture

It turns out there's a policy for deprecating plugins here: https://www.drupal.org/core/deprecation#how-plugin

However, I don't see how it can be used for YAML plugins:

> Add @trigger_error('...', E_USER_DEPRECATED) to the plugin constructor.

YAML plugins *can* define a specific class, but generally they tend to all use a common class. Seems a bit faffy to have to create a new class just to deprecate a plugin.

> Add no_ui = true to the plugin definition. If the plugin does not support no_ui but is selectable in a UI then an issue will be needed to add it.

That's doable at least.

> Also, add an @deprecated and @see phpdoc annotations to the plugin's class docblock.

We can do the same sort of thing to the YAML plugin definition, with a comment or something. But it needs defining.

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

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

quietone’s picture

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

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

andypost’s picture

Priority: Normal » Major

at least it major blocker for many subsystems

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

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

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

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

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

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

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

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

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

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

andypost’s picture

It could use new attribute for plugin classes https://wiki.php.net/rfc/deprecated_attribute

andypost’s picture

Issue tags: +PHP 8.4

The new native #[\Deprecated] attribute in PHP 8.4 can automatically throw deprecation messages, so external libraries can give unexpected deprecations

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

quietone’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -PHP 8.4

I've read through this again and I agree with @larowlan, that this can be closed and discussion can continue in any followups. For example, there is already #3039240: Create a way to declare a plugin as deprecated. And in that issue the documentation can be updated when there is a working implementation.

I am going to set RTBC. I trust if I missed something that should be in a follow, someone will comment.

longwave’s picture

Status: Reviewed & tested by the community » Fixed

Agree there is nothing left to discuss here, we already have docs on how to deprecate PHP plugins. I agree with #47 that we don't have a good way to deprecate YAML plugins, but that's not a problem for a policy issue, that needs someone to open another issue with a proposed implementation.

Closing as fixed and granting credits.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.