Problem/Motivation

Currently service provider for a module called the_module_name must be in a class called Drupal\module\TheModuleName. This naming is rather brittle, very hard to learn (and the decision to do this was made outside of normal core processes).

Steps to reproduce

Proposed resolution

Before going into the proposals, let's note YamlFileLoader has been forked from Symfony because at the time adding the Config component was not desirable however in #2464053: Remove @todo to Improve YamlFileLoader so that we can cache built service definition objects and not just the raw data. Drupal specific file caching was added which makes it fairly impossible to unfork it ever again. Thus, I will not list editing YamlFileLoader as a con.

Several proposals exist:

  1. Add a service_providers key in services.yml. Pros: multiple classes can be registered with ease with any name. Cons: it's a new Drupalism in services.yml.
  2. Call the class Drupal\module\Services or ServiceProvider. Pros: it's very simple, avoids weird naming for more complex module names. Cons: it's still magic naming -- however checking for the all lower case version as well is not too hard to avoid FS problem.
  3. Put the registration in the module info yml (or composer.json). Pros: it keeps the Drupalisms in one place. Cons: alexpott doesn't think it belongs there.
  4. ✅ Make them tagged services. Pros: it's easy and cheap to implement both in core and in modules. Cons: not much? injecting services need to be done with care because the container is still being built but then again both methods of these classes already receive the container and need to be careful with getting services so nothing new is happening here, really.

Remaining tasks

Choose approach 4 has the most votes for now
Review https://git.drupalcode.org/project/drupal/-/merge_requests/11198/diffs
Decide whether ServiceProvider classes should be renamed (as is in the current MR) or keep the ServiceProvider suffix.

User interface changes

N/A

Introduced terminology

N/A

API changes

Service providers are now tagged services

Data model changes

N/A

Release notes snippet

N/A

Original issue summary

In the docs at https://www.drupal.org/docs/8/api/services-and-dependency-injection/alte...

> Note that if you want this service alteration to be recognized automatically, the name of this class is required to be a CamelCase version of your module's machine name followed by ServiceProvider, it is required to be in your module's top-level namespace Drupal\your_module_name, and it must implement \Drupal\Core\DependencyInjection\ServiceModifierInterface (which ServiceProviderBase does).

The relevant code is in discoverServiceProviders().

It seems a bit backwards to be doing magic discovery on a class name, when all other things of this sort are done by explicitly declaring the class -- eg dynamic routes, dynamic permissions.

In line with that pattern, we should declare a dynamic service provider in the module's services.yml file.

Issue fork drupal-2910814

Command icon 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

joachim created an issue. See original summary.

dawehner’s picture

If I understand you correctly you are talking about something like this?

service_providers:
  - \Drupal\...
services:
  ...

I would love that! I've been trying someone to help debugging a problem where something worked on their machine, but not on the testbot. It turned out, they camelcased their module name in the wrong way, and as such had issues with case (in)sensitive file systems.

joachim’s picture

Yes, exactly like that!

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new5.04 KB

Here is just a start for people to play around with it.

Status: Needs review » Needs work

The last submitted patch, 4: 2910814-4.patch, failed testing. View results

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new4.93 KB
new8.86 KB

Here is also a test to prove it works.

The last submitted patch, 6: 2910814-test.patch, failed testing. View results

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.

claudiu.cristea’s picture

#2817627: Make service swapping easier is not a duplicate but it allows overriding services provided by a different module directly in the *.services.yml file.

dawehner’s picture

StatusFileSize
new9 KB
new1000 bytes

I added a deprecation notice for now.

Status: Needs review » Needs work

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

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.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new16.49 KB
new11.55 KB

I tried to test the deprecation, with @expectedDeprecation, in \Drupal\KernelTests\Core\DrupalKernel\DrupalKernelTest::testServiceProviders() but it doesn't work. Have no idea why.

Fixed all core deprecations.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

This is looking really great, I like these changes. I think that the current core deprecation testing is sufficient and that we don't need to add that for this class.

joachim’s picture

Status: Reviewed & tested by the community » Needs work

I think we should add a TODO comment to this bit, to say it needs to be removed before D9:

    // Load each module's serviceProvider class.
    foreach ($module_filenames as $module => $filename) {
      $camelized = ContainerBuilder::camelize($module);
      $name = "{$camelized}ServiceProvider";
      $class = "Drupal\\{$module}\\{$name}";
claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new17.14 KB
new1.37 KB

Added @todo, improved a little around the docs.

joachim’s picture

Status: Needs review » Reviewed & tested by the community

Looks good!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -597,17 +599,41 @@ public function discoverServiceProviders() {
    +      // @todo Remove the implicit class name service provider in Drupal 9.0.x.
    

    I would argue that the deprecation is a much more effective @todo than this comment. Especially if we have a legacy test.

  2. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -597,17 +599,41 @@ public function discoverServiceProviders() {
    +      if (!empty($this->serviceProviderClasses['app'][$module])) {
    +        @trigger_error("Implicit service providers are deprecated in Drupal 8.7.x and will be removed before Drupal 9.0.0. Instead declare your service provider class $class in .services.yml files. See https://www.drupal.org/node/2974194.", E_USER_DEPRECATED);
           }
    

    This should tell you which module has implicit service providers and what they are. This should be tested.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new17.59 KB
new1.88 KB

@alexpott, I tried to test, see my comment from #13 but the deprecation is not catched. Probably it's too early?

Added the test. Regarding the @todo, I think it doesn't hurt.

Status: Needs review » Needs work

The last submitted patch, 19: 2910814-19.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new17.4 KB
new3.35 KB

Finally, I found out that DrupalKernelTest::setUp() is not invoking parent::setUp() and this makes the PHPUnit Bridge not to be in effect. I haven't dig too much to find the exact point where this happens. Creating a new kernel test that is just using parent::setUp() is fixing the problem.

alexpott’s picture

@claudiu.cristea nice sleuthing! Can you open an issue about DrupalKernelTest not having deprecation testing. I agree that fixing that here is out-of-scope.

Re the @todo - there's a standard that an @todo should be created with a corresponding issue. For me adding the deprecation is the @todo and we shouldn't be creating issues against Drupal 9 for every deprecation. Or maybe we should I don't know but to paraphrase @catch "a @todo without an issue is like a scream in space"

claudiu.cristea’s picture

StatusFileSize
new759 bytes
new17.21 KB

Removed the @todo.

Created #3001128: DrupalKernelTest doesn't test deprecation. I will add a "test only" patch there, as soon as this gets in, just to reuse the testing module introduced here.

joachim’s picture

+++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
@@ -353,7 +353,7 @@ private function validate($content, $file)
             throw new InvalidArgumentException(sprintf('The service file "%s" is not valid: it contains invalid keys %s. Services have to be added under "services" and Parameters under "parameters".', $file, $invalid_keys));

Nitpick: the error message could do to mention the new top-level key we are adding here.

Otherwise, RTBC.

alexpott’s picture

The one thing I wonder is are we missing a trick and not doing more of this in \Drupal\Core\DependencyInjection\YamlFileLoader - otoh introducing a drupalism into services.yml files is also interesting.

+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -609,9 +611,30 @@ public function discoverServiceProviders() {
+        // Load service providers from the $module.services.yml file.
+        if (!$content = $file_cache->get($filename)) {
+          $content = Yaml::decode(file_get_contents($filename));
+        }

This is depending on an internal detail of YamlFileLoader outside of YamlFileLoader. That feels pretty odd.

claudiu.cristea’s picture

@alexpott doing that in YamlFileLoader means we have to diverge more our ContainerBuilder in order to store there the service provider classes.

claudiu.cristea’s picture

Alternatively, we ca avoid the drupalism by moving the service provider classes in separate file $module.service_providers.yml

dawehner’s picture

The one thing I wonder is are we missing a trick and not doing more of this in \Drupal\Core\DependencyInjection\YamlFileLoader - otoh introducing a drupalism into services.yml files is also interesting.

At least we replace one kind of Drupalism with sort of one other.

joachim’s picture

> otoh introducing a drupalism into services.yml files is also interesting.

> At least we replace one kind of Drupalism with sort of one other.

And IMO it's a much better Drupalism.

The existing magic classname is a one-off pattern. Nothing else in core behaves like that, expecting the module name in a class name in a certain file location. It's obscure: if you try to find where a service comes from, you don't know to look for this file.

The pattern of declaring a class in a YAML that provides dynamic things is a pattern that is repeated in other parts of core: routes and permissions both do this already. It's also more explicit. You look for service definitions in the services.yml file, and you spot this 'service provider' declaration, and it's pretty clear what it means.

alexpott’s picture

Status: Needs review » Needs work

I totally agree that declaration is much better than magic discovery based on names. It's great to deprecate the magic and replace with a declarative approach and yes doing this inline with things like permissions.

But that still leaves open the how and the where. I think the current approach is the first new thing we've added to Symfony's services.yml files and moving us away from that means that we should take time to carefully consider if and how we do that. I agree with @joachim that a big +1 for putting it in the services.yml file is that this is were we declare a modules services so provider and modifier classes also belong here. A separate yaml file does seem icky and the only other places would be a modules .info.yml or composer.json and I don't think this belongs there. So +1 for putting in the module.services.yml. Also there are a number of Symfony things that we don't support - for example https://symfony.com/doc/current/service_container/import.html#importing-... so this divergence has already occurred.

So now we're extending what goes in services.yml files I think we need to look at our implementation. As noted in #25 the current implementation reaches into the internals of a cache to do an optimised read. That feels wrong. Also the uncached read takes place because we do a read for adding the services so on a completely uncached container rebuild we'll be doing 2 reads of the same file.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

joachim’s picture

Made a MR with patch #23.

Still needs work for various comments above.

nicxvan’s picture

Oh this is very interesting! I wonder if this might work for the install requirements: #3490843: Create class to replace hook_requirements('install')

nicxvan’s picture

Did a pass at calling out what needs to change for tests to run.

I think this looks great, not sure if there is anything to address 25 specifically.

tim.plunkett’s picture

To be clear, this is an MR I made of the branch @joachim of the patch @claudiu.cristea made in 2018. There's definitely a lot of cruft in it.

@nicxvan feel free to push to the MR fork!

nicxvan’s picture

I know, I wanted to just take on reviewing for now.

nicxvan’s picture

I'm gonna apply my comments and work on the other changes needed.

nicxvan’s picture

Fixed the easy stuff, this is going to need a lot more work, currently core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php needs a lot of updates for the new error checking for valid keys.

ghost of drupal past’s picture

As always, I was curious how this came to be.

Well, there's no explanation. The camelize was added in d1e52e0089 which doesn't have an issue ID associated with it neither does the commit message "Various cleanups" tells us anything. This is what happened:

-      $class = "\Drupal\\{$module}\\{$module}Bundle";
+      $camelized = ContainerBuilder::camelize($module);
+      $class = "\Drupal\\{$module}\\{$camelized}Bundle";

And then in #1988508: Stop pretending we support Symfony bundles when we really just have service providers it was merely kept. In that issue effulgenstia had an idea which might or might not be worth reconsidering: call the service provider simply Drupal\modulename\Services.

catch’s picture

Went back a bit further via Google/related issues instead of git blame. I remember I hated the very existence of this, both the code and the way initiatives were ran which produced it.

#1716048: Do not boot bundle classes on every request

#1715940: Remove DIC compilation until it can be dumped to disk which has the choice phrase 'premature optimization' when talking about making changes to what was already a more than ten years old legacy code base.

This might be it. Don't think I was wrong in comment #1 #1599108: Allow modules to register services and subscriber services (events) glad we are finally getting there even if it involved reversing out of a lot of dead ends.

nicxvan’s picture

That was quite the read!

This is going to take some effort though I think.

nicxvan’s picture

Ok, there were a couple of modules with service providers missing the key in services.yml. I added those.

I also moved the service providers above the services key so it's clearer if a module uses one.

Let's see how this does with the tests.

ghost of drupal past’s picture

Issue summary: View changes

I added a few ideas and wrote a new issue summary.

catch’s picture

Talked about this issue briefly with @ghost of drupal past. I'm not entirely sure that diverging from the services.yml format is worth it to avoid magic naming, so wondering about #2 in the issue summary.

ghost of drupal past’s picture

Issue summary: View changes
ghost of drupal past’s picture

Issue summary: View changes
ghost of drupal past’s picture

Issue summary: View changes

ghost of drupal past’s picture

Issue summary: View changes
ghost of drupal past’s picture

Title: deprecate magic ServiceProvider file discovery; declare in services.yml » Deprecate magic ServiceProvider file discovery
Issue summary: View changes
nicxvan’s picture

Call the class Drupal\module\Services or ServiceProvider. Pros: it's very simple, avoids weird naming for more complex module names. Cons: it's still magic naming -- however checking for the all lower case version as well is not too hard to avoid FS problem.

That makes finding a specific one hard to find, even the few test classes that have the same name it's hard to be sure you're in the right one or find it.

I generally navigate to a file using ctrl + E then type it, if there are more than a couple of files with the same name it becomes painful to pick them out.

moduleServiceProvider is magic naming, but at least it helps you find it and the file name tells you which module it's for if you're comparing two service providers.

nicxvan’s picture

Approach number 4 is encouraging!

nicxvan’s picture

Do we want to release the new feature here and do the core conversion / deprecation separately? Or do we want to do it all in one issue?

There are about 20 Service providers in core so it's not too bad to do it all at once.

nicxvan’s picture

ghost of drupal past’s picture

Status: Needs work » Needs review

The tagged services branch is ready for review. I do not think it needs an explicit test, converting LanguageServiceProvider shows it works. I added preliminary code for deprecation, it just needs to be uncommented.

godotislate’s picture

1 small nit/comment on the MR.

On a related tangent, has there been thought about deprecating service providers altogether? A lot of what service providers do can be done with service decorators. (Granted that LanguageServiceProvider setting a container parameter is an exception.)

But allowing services to be instantiated in service providers is a blocker to autowiring core services, as seen in #3295751: Autowire core services that do not require explicit configuration #48.

ghost of drupal past’s picture

I tried to shorten the code by moving things into a service pass but ordering makes it not viable. This is short enough.

ghost of drupal past’s picture

I reimplemented the tagged services branch with an even shorter version -- only DrupalKernel needs change and not much change at that.

nicxvan changed the visibility of the branch 2910814-deprecate-magic-service-provider to hidden.

nicxvan’s picture

Status: Needs review » Needs work

I hid the other MR since this one seems a lot more concise.

@catch mentioned in slack that we can likely do the conversion here too which let's us deprecate too.

I'm going to start on converting the remaining ones.

nicxvan’s picture

Status: Needs work » Needs review

Ok I've converted everything and enabled the deprecation message.

nicxvan’s picture

Issue summary: View changes
ghost of drupal past’s picture

Sorry we have not answered #65 adequately. I checked the core service providers:

  1. multiple providers add registerFormat calls to the http_middleware.negotiation
  2. InlineFormErrorsServiceProvider does not decorate but uses extension. Since it overrides a protected class, a decorator refactoring would be somewhat difficult.
  3. entire service passes are added by some providers
  4. Many modules (layout_builder, mysql, node...) module provides services which require other modules to be installed.

Overall, I do not think this can be dropped.

acbramley’s picture

IMO if we're going to remove the magic naming, we should also support autoconfigure for these new tagged services like we have for EventSubscribers and loggers now.

It seems backwards to me to require less magic and more yaml when we've been progressing so much towards less yaml with autowiring, autoconfiguring, etc.

acbramley’s picture

Why don't we

1. Add autoconfiguration based on the interface similar to https://www.drupal.org/node/3357408
2. Keep class names as is, saves bike shedding a new naming convention and reduces changes
3. Only throw the deprecation if the class has the magic name AND it wasn't already autoconfigured or manually defined in a services.yml

claudiu.cristea’s picture

Should we introduce also “priority” for the tag, same as for destructible services? As it’s about service alterers I can see some value

nicxvan’s picture

I think renaming them is cleaner, how about EarlyServices?

Also, why not do the priority and autoconfigure work in a follow up, this is already a clean and easy to review issue with three things.

  • A new feature
  • A conversion
  • A deprecation

Adding more stuff that can be done in a follow up feels like it is out of scope.

acbramley’s picture

Also, why not do the priority and autoconfigure work in a follow up

I think autoconfigure should be done here so we're not going backwards in terms of now having to define it as a tagged service in yaml, then all of a sudden not having to. Priority imo can be a separate issue as that's entirely new.

I still don't think we should change the names. EarlyServices doesn't make much sense to me. ServiceProvider imo is the best. If we're going to force modules to have to change class names for the sake of it that's even worse.

ghost of drupal past’s picture

  1. The way this currently works, legacy first and then new service providers if their class is not legacy named. We could very easily move the new services first and only fire legacies if they have not fired as services. This indeed would allow not renaming them. However, I am for renaming to show things are changing
  2. Re autoconfigure, sure, I upgraded https://www.drupal.org/node/3357408 to be more clear what is going on.
nicxvan’s picture

The way this currently works, legacy first and then new service providers if their class is not legacy named. We could very easily move the new services first and only fire legacies if they have not fired as services. This indeed would allow not renaming them. However, I am for renaming to show things are changing

I agree with this, but I also agree services is too generic.
I am going to name them ServiceAlter, or Service Register, for the ones that do both I'll split them, how is that?

78.2 is precisely why this should be a follow up.

This is the only magically named class in core, removing this isn't backwards even if we are adding a tag in services.yml

acbramley’s picture

Ok putting aside the autoconfig stuff for now (did not expect that to be so controversial), can we look at allowing the class names to remain as is and only fire a deprecation if it's a magicly named service provider rather than a tagged one?

Otherwise we're telling contrib "your service provider can't be called ServiceProvider"

acbramley’s picture

This is the only magically named class in core, removing this isn't backwards even if we are adding a tag in services.yml

Backwards was referring to requiring more yaml. All the other autodiscovery/autowire/autoconfig stuff we've got into core in the past year is moving to less yaml

acbramley’s picture

Status: Needs review » Needs work

We could very easily move the new services first and only fire legacies if they have not fired as services. This indeed would allow not renaming them. However, I am for renaming to show things are changing

Missed this bit. I think the deprecation is perfect for showing things are changing without being as disruptive. Moving to NW to do the swap.

nicxvan’s picture

Status: Needs work » Needs review

I didn't see your comments, I just finished renaming them to be service alter or service register depending on which they are doing.

That way we keep the simplest deprecation and the classes now actually describe what they are doing.

Service provider isn't what they are either.

I hope this is acceptable, I think it will be really confusing to keep the name the same and tell people they have to put the yaml, with the rename, which is just renaming the file and the class they can tag it, otherwise I think it seems like what you're saying, adding the tag for no reason.

Otherwise we're telling contrib "your service provider can't be called ServiceProvider"

Yep, but that's a clean way to tell people to add the tag too. Also what does service provider mean semantically I think these new names are more descriptive anyway.

ghost of drupal past’s picture

I upgraded https://www.drupal.org/node/3357408 to be quite a bit more clear about what is happening and crucially removed the link to the Symfony documentation because Drupal only autoconfigures registered services -- Symfony picks classes up from the filesystem and registers them as services so it was quite a bit misleading as to what autoconfigure means to Drupal.

Now that I stepped through what autoconfiguration does, it's quite clear it does not apply here since autoconfiguration is handled by RegisterAutoconfigureAttributesPass and this runs before any service passes. It needs to. (A few days ago I tried to convert it to a pass, it just doesn't work.)

I rebased on 11.x.

acbramley’s picture

Re #83

That way we keep the simplest deprecation and the classes now actually describe what they are doing.
Service provider isn't what they are either.

But it's simpler if we don't force modules to change class names? The classes extend ServiceProviderInterface, a class name with ServiceProvider in it seems to describe it well.

Also, if we force a name change now it means come Drupal 12 modules will technically be able to use that name again. It just seems odd to force that IMO.

...otherwise I think it seems like what you're saying, adding the tag for no reason.

The reason should be basically the same as why this issue itself exists? Is it for performance, or just that magic naming is bad? Either way that's justification enough IMO. I think it's stranger to artificially force a name change for 1 major version of Drupal in the sake of making it seem like there's a reason to? If that makes sense 😅

Re #84
Thanks for the clarification! I would love to see services autoregistered as well, We want to do that with loggers (see #3395439: Automatically create a logger channel for autoconfigured modules) and it could definitely work for this service provider tagged service and event subscribers too.

I'm still not seeing a good reason to force the name change, I won't change the status again though as maybe we need another opinion?

I'm coming at this from a DX perspective, the change from magic naming is good, just not the forced name change IMO.

ghost of drupal past’s picture

To clarify what #83 says, if there's no rename then people won't understand why they need to tag it. But, the rename is not forced. Core does the renames to be more clear, contrib can do whatever they want. I just pushed a version where the tagged services fire first and then if any magic named classes remain then they fire and trigger the deprecation. Previously it was the other way 'round which meant if someone actually injected something in the service definition it wouldn't have worked -- but never was a forced rename proposed. If contrib wants to keep name, sure they can -- in fact I expect most contrib in the beginning to keep 'em so they can maintain a single branch.

nicxvan’s picture

Oh I like that compromise.

acbramley’s picture

but never was a forced rename proposed

Thanks, it certainly was made to sound that way!

Still think it'd be better to leave core as is in case someone is doing something with these classes but I'm happy as long as we're not forcing the change :)

ghost of drupal past’s picture

> in case someone is doing something with these classes

https://www.drupal.org/about/core/policies/core-change-policies/bc-policy basically everything that is like a "herd" implementation of an interface is not BC, specifically listed are plugins, paramconverters, entity handler etc. Also, it is not at all clear why would anyone want to, changing services has its own interface. Perhaps to reach a utility function but the only provider with a utility function is languageserviceprovider and that's not used in contrib https://git.drupalcode.org/search?group_id=2&scope=blobs&search=language... and since the functions are isMultilingual / getDefaultLanguageValue it's hard to see why custom code would need 'em , surely you know whether your site is multilingual or not. Oh and protected methods are also exempt from BC so you shouldn't be using them anyways. So: the class is exempted, the methods are exempted and they are not used for what little there is.

And, once again, the code in DrupalKernel ever since this idea came up always allowed for renaming or not renaming. This is not my first rodeo :)

acbramley’s picture

Status: Needs review » Needs work

I've tested this locally and there's a few issues.

1. The trigger_error wasn't throwing a deprecation, this has uncovered some providers that haven't been converted (e.g InstallerServiceProvider) - I've applied a fix for this.
2. Deprecations are still thrown if a class is named with the old magic naming. I tested this by reverting FileServiceAlter to FileServiceProvider and running a Kernel test. The deprecation is still thrown even with an entry in file.services.yml
3. Other random things are throwing deprecations now:

Service providers are now tagged services with the service_provider tag. Magic naming for Test is deprecated in drupal:11.2.0 and removed in drupal:12.0.0.
Service providers are now tagged services with the service_provider tag. Magic naming for core is deprecated in drupal:11.2.0 and removed in drupal:12.0.0.
Service providers are now tagged services with the service_provider tag. Magic naming for Drupal\mysql\MysqlServiceRegister is deprecated in drupal:11.2.0 and removed in drupal:12.0.0.
acbramley’s picture

ghost of drupal past’s picture

Status: Needs work » Needs review

Thanks! Yes, that's a recent oversight from #86. Please test again and if there are still unexpected fails, I will need reproduction instructions but I think we are good now.

acbramley’s picture

Status: Needs review » Needs work

Tests are failing on non magic named things

Magic naming for Drupal\workspaces\WorkspacesServiceAlter...

Also can still reproduce my previous report of magic named classes still throwing errors with the new service_provider tag.

Magic naming for Drupal\file\FileServiceProvider is deprecated in drupal:11.2.0 and removed in drupal:12.0.0. Service providers are now tagged services with the service_provider tag. See https://www.drupal.org/node/2974194

Steps to reproduce this are applying the following diff:

diff --git a/core/modules/file/file.services.yml b/core/modules/file/file.services.yml
index b30f942c387..95c0c0c8e72 100644
--- a/core/modules/file/file.services.yml
+++ b/core/modules/file/file.services.yml
@@ -37,6 +37,6 @@ services:
     arguments: ['@file_system']
   Drupal\file\Upload\InputStreamFileWriterInterface: '@file.input_stream_file_writer'
   file.service_provider:
-    class: Drupal\file\FileServiceAlter
+    class: Drupal\file\FileServiceProvider
     tags:
       - { name: service_provider }
diff --git a/core/modules/file/src/FileServiceAlter.php b/core/modules/file/src/FileServiceProvider.php
similarity index 91%
rename from core/modules/file/src/FileServiceAlter.php
rename to core/modules/file/src/FileServiceProvider.php
index 4dc34fe2a6e..b22f3c69283 100644
--- a/core/modules/file/src/FileServiceAlter.php
+++ b/core/modules/file/src/FileServiceProvider.php
@@ -9,7 +9,7 @@
 /**
  * Adds 'application/octet-stream' as a known (bin) format.
  */
-class FileServiceAlter implements ServiceModifierInterface {
+class FileServiceProvider implements ServiceModifierInterface {
 
   /**
    * {@inheritdoc}

ghost of drupal past’s picture

OK and after naming it back, what are you running? It's going to be something tests do, I bet...

acbramley’s picture

@ghost of drupal past just running a random test that installs file module. In this case DownloadTest::testPublicFileTransfer.

I think the test failures in CI are showing that there's more to it seeing as non-magically named services that are tagged are also throwing errors.

I can also put a breakpoint on the trigger_error line and hit it via a drush cr which throws these:

PHP Deprecated: Magic naming for Drupal\file\FileServiceProvider is deprecated in drupal:11.2.0 and removed in drupal:12.0.0. Service providers are now tagged services with the service_provider tag. See https://www.drupal.org/node/2974194 in /data/app/core/lib/Drupal/Core/DrupalKernel.php on line 1384
PHP Deprecated: Magic naming for Drupal\mysql\MysqlServiceRegister is deprecated in drupal:11.2.0 and removed in drupal:12.0.0. Service providers are now tagged services with the service_provider tag. See https://www.drupal.org/node/2974194 in /data/app/core/lib/Drupal/Core/DrupalKernel.php on line 1384
ghost of drupal past’s picture

OK. The problem was tagged services marked with servicemodifierinterace got added to the service provider objects list before depreciation message hit so those were thought to be deprecated.

(MysqlServiceRegister should be changed to implement only one of the interfaces.)

ghost of drupal past’s picture

Status: Needs work » Needs review

jsonapi was left behind, I converted it.

acbramley’s picture

Nice, that latest commit has fixed both issues.

I do still think we should keep core classes as they were to cover us from these weird bugs in the future. That way we won't regress for contrib.

ghost of drupal past’s picture

We are now running in circles. I thought the question of renaming was resolved in #88.

acbramley’s picture

@ghost of drupal past no it was not resolved. I don't see the point in renaming core classes if it's not needed, especially since it's potentially hiding bugs from what we can see from my manual testing.

Now things are getting even weirder with the jsonapi split. We have class JsonapiServiceAlter implements ServiceModifierInterface where the other *ServiceAlter classes are extending ServiceProviderInterface. And
class JsonapiServiceRegister implements ServiceProviderInterface

I think I see where the *Alter and *Register are coming from though. They are matching the methods they are implementing (alter from ServiceModifierInterface and register from ServiceProviderInterface). However, classes that extend ServiceProviderBase which implements both don't fit here, this base class is used a lot by core and contrib.

nicxvan’s picture

As mentioned it's to illustrate they can be renamed. We could see what each is doing and find a name that is unique and split them further.

However, I think that's follow up territory.

Yes alter and register are based on the method.

The alters should probably use ServiceModifierInterface
And register should probably use ServiceProviderInterface

ghost of drupal past changed the visibility of the branch 2910814-deprecate-magic-service-provider to active.

ghost of drupal past changed the visibility of the branch 2910814-tagged-services to hidden.

ghost of drupal past’s picture

Status: Needs review » Needs work

OK back to the service_providers approach it seems, our approach has failed to gain acceptance.

ghost of drupal past’s picture

Issue summary: View changes

acbramley changed the visibility of the branch 2910814-tagged-services to active.

nicxvan’s picture

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

I wouldn't be too hasty, there is one person against renaming, and two for it, we can get other opinions.

Also if other's also agree that we shouldn't rename, we can always name everything back to serviceProvider and just tag them.

Putting this back to needs review so we can gather other opinions.

acbramley’s picture

Yes please don't take my disagreement on renaming as a disagreement on the change as a whole, I have said that overall this is great. I am just trying to get it into a state that I think would be easiest for a committer to review and commit, and in my mind the renaming could block that and turn into a bike shedding exercise of what things should be called.

With that being said, I will happily concede the naming if it means getting this in faster.

acbramley changed the visibility of the branch 2910814-deprecate-magic-service-provider to hidden.

nicxvan’s picture

Baseline seems out of sync.

If you would not mind asking core dev their opinion on renaming, no need to bike shed more here. If a core committer agrees I'll rename everything back.

acbramley’s picture

Baseline is fixed

acbramley’s picture

Issue summary: View changes
nicxvan’s picture

False alarm

Baseline is still out of sync, but i think it's a different issue.

https://git.drupalcode.org/project/drupal/-/merge_requests/11198/diffs?c...

Those were not changed in this issue.
They were fixed here: https://www.drupal.org/project/drupal/issues/3483146

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

nicxvan’s picture

Status: Needs work » Needs review

Rebased.

godotislate’s picture

Are service providers considered internal, and not API? Service providers aren't mentioned specifically in the BC policy. The closest thing is that compiler passes are considered internal, and it certainly seems like service providers should not be considered API. (It's also really hard for me to imagine how contrib/custom modules would be extending core service providers.)

But if that is not generally understood, then with the service provider classes being moved/split, there probably should be deprecation messages to that effect. Classes that are moved can use the new container parameters from https://www.drupal.org/node/3509577 to deprecate the old class name.

nicxvan’s picture

Good question!

godotislate’s picture

Will doing the deprecation alleviate concerns about renaming? Adding the container parameters aliases the old class name to the new class name and provides BC, though the added typehints would be a breaking change for any implementing subclass methods.

ghost of drupal past’s picture

Let me restate #89: while the letter of the law doesn't include service providers the spirit of it certainly does. The way I read https://www.drupal.org/about/core/policies/core-change-policies/bc-policy basically everything that is like a "herd" implementation of an interface is not BC, specifically listed are plugins, paramconverters, entity handler etc.

It only makes sense TBH. You should only be interacting with the interface not the specific classes.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

nicxvan’s picture

Status: Needs work » Needs review

Rebased.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

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.