8000 [DI][DX] Allow exclude to be an array of patterns by magnetik · Pull Request #27075 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DI][DX] Allow exclude to be an array of patterns #27075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[DI][DX] Allow exclude to be an array of patterns (taking #24428 over)
  • Loading branch information
magnetik committed May 9, 2018
commit 3ae3a03f41c34d6224cd9787c8ca111f7a8a71a4
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class PrototypeConfigurator extends AbstractServiceConfigurator

private $loader;
private $resource;
private $exclude;
private $excludes;
private $allowParent;

public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent)
Expand All @@ -63,19 +63,21 @@ public function __destruct()
parent::__destruct();

if ($this->loader) {
$this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->exclude);
$this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->excludes);
}
$this->loader = null;
}

8000 /**
* Excludes files from registration using a glob pattern.
* Excludes files from registration using glob patterns.
*
* @param string[]|string $excludes
*
* @return $this
*/
final public function exclude(string $exclude)
final public function exclude($excludes)
{
$this->exclude = $exclude;
$this->excludes = (array) $excludes;

return $this;
}
Expand Down
16 changes: 8 additions & 8 deletions src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ public function __construct(ContainerBuilder $container, FileLocatorInterface $l
/**
* Registers a set of classes as services using PSR-4 for discovery.
*
* @param Definition $prototype A definition to use as template
* @param string $namespace The namespace prefix of classes in the scanned directory
* @param string $resource The directory to look for classes, glob-patterns allowed
* @param string $exclude A globed path of files to exclude
* @param Definition $prototype A definition to use as template
* @param string $namespace The namespace prefix of classes in the scanned dir 8000 ectory
* @param string $resource The directory to look for classes, glob-patterns allowed
* @param string|string[]|null $exclude A globbed path of files to exclude or an array of globbed paths of files to exclude
*/
public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null)
{
Expand All @@ -54,7 +54,7 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e
throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: %s.', $namespace));
}

$classes = $this->findClasses($namespace, $resource, $exclude);
$classes = $this->findClasses($namespace, $resource, (array) $exclude);
// prepare for deep cloning
$serializedPrototype = serialize($prototype);
$interfaces = array();
Expand Down Expand Up @@ -101,14 +101,14 @@ protected function setDefinition($id, Definition $definition)
}
}

private function findClasses($namespace, $pattern, $excludePattern)
private function findClasses($namespace, $pattern, array $excludePatterns)
{
$parameterBag = $this->container->getParameterBag();

$excludePaths = array();
$excludePrefix = null;
if ($excludePattern) {
$excludePattern = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePattern));
$excludePatterns = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePatterns));
foreach ($excludePatterns as $excludePattern) {
foreach ($this->glob($excludePattern, true, $resource) as $path => $info) {
if (null === $excludePrefix) {
$excludePrefix = $resource->getPrefix();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,14 @@ private function parseDefinitions(\DOMDocument $xml, $file, $defaults)
foreach ($services as $service) {
if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) {
if ('prototype' === $service->tagName) {
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), (string) $service->getAttribute('exclude'));
$excludes = array_column($this->getChildren($service, 'exclude'), 'nodeValue');
if ($service->hasAttribute('exclude')) {
if (count($excludes) > 0) {
throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
}
$excludes = array($service->getAttribute('exclude'));
}
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes);
} else {
$this->setDefinition((string) $service->getAttribute('id'), $definition);
}
Expand Down
8000
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
<xsd:attribute name="namespace" type="xsd:string" use="required" />
<xsd:attribute name="resource" type="xsd:string" use="required" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

services:
service_container:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo
public: true
tags:
- { name: foo }
- { name: baz }
deprecated: "%service_id%"
arguments: [1]
factory: f
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar
public: true
tags:
- { name: foo }
- { name: baz }
deprecated: "%service_id%"
lazy: true
arguments: [1]
factory: f
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;

return function (ContainerConfigurator $c) {
$di = $c->services()->defaults()
->tag('baz');
$di->load(Prototype::class.'\\', '../Prototype')
->autoconfigure()
->exclude(array('../Prototype/OtherDir', '../Prototype/BadClasses'))
->factory('f')
->deprecate('%service_id%')
->args(array(0))
->args(array(1))
->autoconfigure(false)
->tag('foo')
->parent('foo');
$di->set('foo')->lazy()->abstract();
$di->get(Prototype\Foo::class)->lazy(false);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*">
<exclude>../Prototype/OtherDir</exclude>
<exclude>../Prototype/BadClasses</exclude>
</prototype>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ public function testRegisterClassesWithExclude()
);
}

public function testRegisterClassesWithExcludeAsArray()
{
$container = new ContainerBuilder();
$container->setParameter('sub_dir', 'Sub');
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$loader->registerClasses(
new Definition(),
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\',
'Prototype/*', array(
'Prototype/%sub_dir%',
'Prototype/OtherDir/AnotherSub/DeeperBaz.php',
)
);
$this->assertTrue($container->has(Foo::class));
$this->assertTrue($container->has(Baz::class));
$this->assertFalse($container->has(Bar::class));
$this->assertFalse($container->has(DeeperBaz::class));
}

public function testNestedRegisterClasses()
{
$container = new ContainerBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,26 @@ public function testPrototype()
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources);
}

public function testPrototypeExcludeWithArray()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_prototype_array.xml');

$ids = array_keys($container->getDefinitions());
sort($ids);
$this->assertSame(array(Prototype\Foo::class, Prototype\Sub\Bar::class, 'service_container'), $ids);

$resources = $container->getResources();

$fixturesDir = dirname(__DIR__).DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR;
$this->assertTrue(false !== array_search(new FileResource($fixturesDir.'xml'.DIRECTORY_SEPARATOR.'services_prototype_array.xml'), $resources));
$this->assertTrue(false !== array_search(new GlobResource($fixturesDir.'Prototype', '/*', true), $resources));
$resources = array_map('strval', $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo', $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources);
}

/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid attribute "class" defined for alias "bar" in
Expand Down
0