Follow-up of #3084983: Move all the code related to path aliases to a new (required) "path_alias" module.

Adding the deprecated service back fixes subpathauto: #3093377: Fix the failing HEAD. While I think the implementation there is somewhat problematic, it will work fine on 8.7 and 8.8 if we just have the service, without adding the tags that would result in it being called twice.

The second is a bit bigger, in #3093401: Compatibility with Drupal 8.8.0-beta1 there has been quite a bit of confusion around the BC vs. real service definitions. Right now, the BC version is defined in core.services.yml while the real one that is used except while running the updates (and drush bootstrap as we've found out), so that's the one that PhpStorm and also manual discovery finds, and then phpstorm complains about incompatible type hints. I have this idea that we could invert it by moving the real ones to path_alias.services.yml and then adding in the ones that are currently in core.services.yml in CoreServiceProvider. Need to see if that actually works.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir created an issue. See original summary.

Berdir’s picture

Status: Active » Needs review
FileSize
651 bytes

First part, confirmed that this fixes the subpathauto tests, just need to install the entity type in kernel tests then and there are also existing, unrelated issues with the kernel test.

Berdir’s picture

Here's a first attempt. Might not have gotten the deprecations quite right yet, but I found some interesting bits in PathAliasServiceProvider, for example it actually tries to deprecate path_processor_alias and path_subscriber but it fails to do so because these services actually don't exist anymore. So that was supposed to work but broken.

The problem with this idea of dynamically adding it is that it breaks static analysis including IDE's, so they don't know that path.alias_manager/storage are deprecated. so I think that should be there explicitly.

Also not sure why some services only had the deprecated comment above instead of the definition, the thing is that upgrade path tests are *allowed* to trigger deprecation messages, so as long as the fallback in CoreServiceProvider is only triggered in core, we're fine. seems to work OK with a few example tests that I did run locally, lets see about the rest.

The changes in core.services.yml might be a bit confusing, but I've attached a diff against core *before* the original patch was committed and it's pretty clear then, the only service that is removed is path.alias_repository because that was new in 8.8 and doesn't need BC. The others are there, with deprecated: definition just without tags. I've done the same in CoreServiceProvider btw, that means they wont' be called until the module is installed, but that's fine, we're not supposed to do caching and alias lookup during the upgrade path anyway.

Berdir’s picture

I've also verified that together with the patch above, the patch from comment #5 in #3093401: Compatibility with Drupal 8.8.0-beta1 no longer shows a warning in pathauto.services.yml, although we can't commit that for different reasons.

plach’s picture

This makes sense to me, it should in fact make BC easier and more understandable for both humans and softwares :)
We will need to update the original CR to mark the tagged services as deprecated rather than replaced, once this is committed.

  1. +++ b/core/core.services.yml
    --- a/core/lib/Drupal/Core/CoreServiceProvider.php
    +++ b/core/lib/Drupal/Core/CoreServiceProvider.php
    

    I think it would be good to add a kernel test not installing path_alias and providing test coverage for this, otherwise we might break the BC layer down the line without realizing it. I originally thought that an example of this could be adding a constructor parameter to one of the new services, but on a second thought this should not affect the legacy services, as they would likely be untouched.

  2. +++ b/core/lib/Drupal/Core/CoreServiceProvider.php
    @@ -116,6 +122,51 @@ public function alter(ContainerBuilder $container) {
    +    // @todo Remove this in Drupal 9 in https://www.drupal.org/node/3092090
    

    Nit: missing trailing dot.

plach’s picture

We should also update the comment at AliasManager::__construct():

      // ...
      catch (ServiceCircularReferenceException $e) {
        // This may happen during installation when "path_alias" has not swapped
        // the alias manager class yet. Nothing to do in this case.
      }
dww’s picture

Re: #5.2: I thought we specifically don't want a trailing dot at the end of a URL, since then if you try to click on it you often get a broken link.

https://www.drupal.org/node/3092090.

(edit: I guess the d.o filter is smarter than a lot of other filters that turn links into links). ;)

That said, I believe the truly standards-compliant solution is this:

    // @todo Remove this in Drupal 9.
    // @see https://www.drupal.org/node/3092090

*shrug*

Meanwhile, looking at #3:

  1. +++ b/core/lib/Drupal/Core/CoreServiceProvider.php
    @@ -116,6 +122,51 @@ public function alter(ContainerBuilder $container) {
    +      if (!$container->hasDefinition($id)) {
    +        $definition = $container->register($id, $class);
    

    This is the only thing shared across all the cases. I wonder if the array and switch() are actually helpful, or if it'd be clearer to just have 5 calls to $container->register(), each with exactly what's needed for that service/class.

  2. +++ b/core/lib/Drupal/Core/CoreServiceProvider.php
    @@ -116,6 +122,51 @@ public function alter(ContainerBuilder $container) {
    +          case 'path_alias.whitelist':
    +            $definition->addArgument('path_alias_whitelist');
    +            $definition->addArgument(new Reference('cache.bootstrap'));
    

    I haven't fully wrapped my head around this, but it's not immediately obvious why this one doesn't need the new Reference() and all the others do... Maybe a code comment would be helpful for mere mortals like myself to understand?

Berdir’s picture

Thanks for the reviews, some comments in case someone else wants to update it while I sleep (which I should be doing now)

#5.1: No can do, kernel tests now always install path_alias for BC: #3093257: Install path_alias by default in kernel tests to minimize the impact on contrib tests supporting 8.7.x, but I'd expect update tests to fail if things are missing, will do some testing, and we should also do some manual testing.

#5.2: yeah, that's always a bit ugly, actually explicitly removed it, due to the URL thing. But can add it back, no big deal. I think we leave it out on @deprecated on purpose.

#7: @see must only be used in a docblock and never as inline conmment. That can't be parsed in a meaningful way.

#7.1: I kind of like the pattern, but no strong feelings. if we wouldn't need the hasDefinition() check, maybe, but I think it that would make it quite repetitive, as each block would need to be in a if condition and have the service ID duplicated.

#7.2: Because unlike everything else, it's not a reference, it is actually a string.

plach’s picture

@Berdir:

#5.1: No can do, kernel tests now always install path_alias for BC [...]

Fairly sure we can still do it by overriding KernelTestBase::enableModules() :)

Berdir’s picture

Fairly sure we can still do it by overriding KernelTestBase::enableModules() :)

Nice idea, but setup doesn't use enableModules(), it does use \Drupal\KernelTests\KernelTestBase::getModulesToEnable() and \Drupal\KernelTests\KernelTestBase::getExtensionsForModules() to inject them directly into the kernel and these functions are private.

Maybe with some reflection magic, but I don't think this is worth it?

As I said, I did verify that the update test are failing if this isn't there, and they do, hard:

Symfony\Component\DependencyInjection\Exception\InvalidArgumentException : Unable to replace alias "path.alias_whitelist" with actual definition "path_alias.whitelist".
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "path_alias.whitelist".

In case you want to try yourself, this is the test I had:

namespace Drupal\KernelTests\Core\Path;

use Drupal\Core\EventSubscriber\PathSubscriber;
use Drupal\Core\Path\AliasManager;
use Drupal\Core\Path\AliasRepository;
use Drupal\Core\Path\AliasWhitelist;
use Drupal\Core\PathProcessor\PathProcessorAlias;
use Drupal\KernelTests\KernelTestBase;

/**
 * @group path
 * @group legacy
 */
class LegacyPathAliasServicesTest extends KernelTestBase {

  /**
   * Tests that the path_alias.module services have fallbacks defined.
   */
  public function testBCServices() {
    $this->assertFalse($this->container->get('module_handler')->moduleExists('path_alias'));
    $this->assertEquals(AliasRepository::class, get_class($this->container->get('path_alias.repository')));
    $this->assertEquals(AliasWhitelist::class, get_class($this->container->get('path_alias.whitelist')));
    $this->assertEquals(PathSubscriber::class, get_class($this->container->get('path_alias.subscriber')));
    $this->assertEquals(PathProcessorAlias::class, get_class($this->container->get('path_alias.path_processor')));
    $this->assertEquals(AliasManager::class, get_class($this->container->get('path_alias.manager')));
  }

minus non-working method overrides.

So, only fixed the two comment things, fine with adding dot, at least now for me in PHPStorm the . is not included in the URL now, not sure when it is and when not.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Patch looks good to me. Moving the defintions make sense to me. Just one question.

+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -116,6 +122,51 @@ public function alter(ContainerBuilder $container) {
+    // Look for missing services that are now defined by the path_alias module,
+    // add them as a fallback until the module is installed.

Do we want to add specific tests for this?

Edit: @Berdir said that in slack explicit test coverage for that is surprisingly hard but each upgrade path test is testing it

plach’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for the updated patch! On a second look I think we need deprecation testing for the two restored services. We can probably add a couple of test methods to Drupal\Tests\path_alias\Kernel\DeprecatedServicesTest.

I'm also wondering whether we should add a quick CR to warn early adopters about this, or whether updating the previous one is enough.

Nice idea, but setup doesn't use enableModules(), it does use \Drupal\KernelTests\KernelTestBase::getModulesToEnable() and \Drupal\KernelTests\KernelTestBase::getExtensionsForModules() to inject them directly into the kernel and these functions are private.

Ouch, I looked at the wrong KernelTestBase (the simpletest one). I guess I can live with implicit test coverage if writing an explicit test is not worth the effort.

Berdir’s picture

Status: Needs work » Needs review
FileSize
13.41 KB
1.08 KB

What about extending an existing method like this? kernel tests are fairly fast but still slow compared to unit tests, so I prefer to group things together when it's easy.

About the CR, IMHO we should update the existing one. I already think the two separate ones for the alias storage and the path_alias module are tricky and we should at least cross-reference them. I also had a look at modules using those services, the good thing is that there aren't too many:

http://grep.xnddx.ru/search?text=path_processor_alias
http://grep.xnddx.ru/search?text=path_subscriber

plach’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks!

amateescu’s picture

Looks great to me as well, +10 for RTBC :)

  • plach committed ba96437 on 9.0.x
    Issue #3093747 by Berdir: Add alias process service back (deprecated)...

  • plach committed 2f9da17 on 8.9.x
    Issue #3093747 by Berdir: Add alias process service back (deprecated)...

  • plach committed 10d6e14 on 8.8.x
    Issue #3093747 by Berdir: Add alias process service back (deprecated)...
plach’s picture

Status: Reviewed & tested by the community » Fixed

Committed ba96437 and pushed to 9.0.x and friends. Thanks!

plach’s picture

xjm’s picture

This may also need update the release note for the path_alias change, and we should mention it in the beta2 or rc1 notes as a resolved regression from beta1.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.