bug #40917 [Config][DependencyInjection] Uniformize trailing slash handling (dunglas)

This PR was squashed before being merged into the 4.4 branch.

Discussion
----------

[Config][DependencyInjection] Uniformize trailing slash handling

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | n/a
| License       | MIT
| Doc PR        | n/a

Currently, the handling of trailing slashes in file loaders exclusion rules is inconsistent, which can create hard to debug issues.

Example:

```yaml
services:
    App\:
        resource: '../src/'
        exclude:
            # This works
            - '../src/FooBar/DependencyInjection/'
            - '../src/FooBar/DependencyInjection'
            - '../src/FooBar/DependencyInjection/*'
            - '../src/*/DependencyInjection'
            - '../src/*/DependencyInjection/*'

            # This doesn't work
            - '../src/*/DependencyInjection/'
```

This PR fixes this subtle issue.

Commits
-------

dc50aa3b55 [Config][DependencyInjection] Uniformize trailing slash handling
This commit is contained in:
Nicolas Grekas 2021-05-07 15:37:58 +02:00
commit 0e738ef170
8 changed files with 56 additions and 4 deletions

View File

@ -82,8 +82,8 @@ abstract class FileLoader extends Loader
$excluded = [];
foreach ((array) $exclude as $pattern) {
foreach ($this->glob($pattern, true, $_, false, true) as $path => $info) {
// normalize Windows slashes
$excluded[str_replace('\\', '/', $path)] = true;
// normalize Windows slashes and remove trailing slashes
$excluded[rtrim(str_replace('\\', '/', $path), '/')] = true;
}
}

View File

@ -127,6 +127,28 @@ class FileLoaderTest extends TestCase
$this->assertCount(2, $loadedFiles);
$this->assertNotContains('ExcludeFile.txt', $loadedFiles);
}
/**
* @dataProvider excludeTrailingSlashConsistencyProvider
*/
public function testExcludeTrailingSlashConsistency(string $exclude)
{
$loader = new TestFileLoader(new FileLocator(__DIR__.'/../Fixtures'));
$loadedFiles = $loader->import('ExcludeTrailingSlash/*', null, false, null, $exclude);
$this->assertCount(2, $loadedFiles);
$this->assertNotContains('baz.txt', $loadedFiles);
}
public function excludeTrailingSlashConsistencyProvider(): iterable
{
yield [__DIR__.'/../Fixtures/Exclude/ExcludeToo/'];
yield [__DIR__.'/../Fixtures/Exclude/ExcludeToo'];
yield [__DIR__.'/../Fixtures/Exclude/ExcludeToo/*'];
yield [__DIR__.'/../Fixtures/*/ExcludeToo'];
yield [__DIR__.'/../Fixtures/*/ExcludeToo/'];
yield [__DIR__.'/../Fixtures/Exclude/ExcludeToo/*'];
yield [__DIR__.'/../Fixtures/Exclude/ExcludeToo/AnotheExcludedFile.txt'];
}
}
class TestFileLoader extends FileLoader

View File

@ -177,6 +177,7 @@ class GlobResourceTest extends TestCase
$expected = [
$dir.'/Exclude/ExcludeToo/AnotheExcludedFile.txt',
$dir.'/ExcludeTrailingSlash/exclude/baz.txt',
$dir.'/foo.xml',
];

View File

@ -166,8 +166,8 @@ abstract class FileLoader extends BaseFileLoader
$excludePrefix = $resource->getPrefix();
}
// normalize Windows slashes
$excludePaths[str_replace('\\', '/', $path)] = true;
// normalize Windows slashes and remove trailing slashes
$excludePaths[rtrim(str_replace('\\', '/', $path), '/')] = true;
}
}

View File

@ -239,6 +239,35 @@ class FileLoaderTest extends TestCase
'yaml/*'
);
}
/**
* @dataProvider excludeTrailingSlashConsistencyProvider
*/
public function testExcludeTrailingSlashConsistency(string $exclude)
{
$container = new ContainerBuilder();
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$loader->registerClasses(
new Definition(),
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\',
'Prototype/*',
$exclude
);
$this->assertTrue($container->has(Foo::class));
$this->assertFalse($container->has(DeeperBaz::class));
}
public function excludeTrailingSlashConsistencyProvider(): iterable
{
yield ['Prototype/OtherDir/AnotherSub/'];
yield ['Prototype/OtherDir/AnotherSub'];
yield ['Prototype/OtherDir/AnotherSub/*'];
yield ['Prototype/*/AnotherSub'];
yield ['Prototype/*/AnotherSub/'];
yield ['Prototype/*/AnotherSub/*'];
yield ['Prototype/OtherDir/AnotherSub/DeeperBaz.php'];
}
}
class TestFileLoader extends FileLoader