Skip to content

Commit

Permalink
feature #21408 [DI] Add ContainerBuilder::fileExists() for checking/t…
Browse files Browse the repository at this point in the history
…racking resource existence (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Add ContainerBuilder::fileExists() for checking/tracking resource existence

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #20189, #20189 (comment)
| License       | MIT
| Doc PR        | n/a

~~Finishes #20189 Adds a convenient `ContainerBuilder::fileExists()` method as suggested by Nicolas and use it to track resources in the FrameworkExtension, adding some missing ones.

Commits
-------

6b556b8 [DI] Add ContainerBuilder::fileExists()
  • Loading branch information
nicolas-grekas committed Feb 2, 2017
2 parents 46daa35 + 6b556b8 commit 35a49fb
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 33 deletions.
Expand Up @@ -13,7 +13,6 @@

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Config\Resource\FileResource;

/**
* Registers additional validators.
Expand Down Expand Up @@ -60,9 +59,8 @@ private function updateValidatorMappingFiles(ContainerBuilder $container, $mappi

foreach ($container->getParameter('kernel.bundles') as $bundle) {
$reflection = new \ReflectionClass($bundle);
if (is_file($file = dirname($reflection->getFileName()).'/'.$validationPath)) {
if ($container->fileExists($file = dirname($reflection->getFileName()).'/'.$validationPath)) {
$files[] = $file;
$container->addResource(new FileResource($file));
}
}

Expand Down
Expand Up @@ -24,7 +24,6 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;
Expand Down Expand Up @@ -875,32 +874,28 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
}
$rootDir = $container->getParameter('kernel.root_dir');
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
if (is_dir($dir = $bundle['path'].'/Resources/translations')) {
if ($container->fileExists($dir = $bundle['path'].'/Resources/translations')) {
$dirs[] = $dir;
}
if (is_dir($dir = $rootDir.sprintf('/Resources/%s/translations', $name))) {
if ($container->fileExists($dir = $rootDir.sprintf('/Resources/%s/translations', $name))) {
$dirs[] = $dir;
}
}

foreach ($config['paths'] as $dir) {
if (is_dir($dir)) {
if ($container->fileExists($dir)) {
$dirs[] = $dir;
} else {
throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir));
}
}

if (is_dir($dir = $rootDir.'/Resources/translations')) {
if ($container->fileExists($dir = $rootDir.'/Resources/translations')) {
$dirs[] = $dir;
}

// Register translation resources
if ($dirs) {
foreach ($dirs as $dir) {
$container->addResource(new DirectoryResource($dir));
}

$files = array();
$finder = Finder::create()
->followLinks()
Expand Down Expand Up @@ -1006,19 +1001,16 @@ private function getValidatorMappingFiles(ContainerBuilder $container, array &$f
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
$dirname = $bundle['path'];

if (is_file($file = $dirname.'/Resources/config/validation.yml')) {
if ($container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)) {
$files['yml'][] = $file;
$container->addResource(new FileResource($file));
}

if (is_file($file = $dirname.'/Resources/config/validation.xml')) {
if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) {
$files['xml'][] = $file;
$container->addResource(new FileResource($file));
}

if (is_dir($dir = $dirname.'/Resources/config/validation')) {
if ($container->fileExists($dir = $dirname.'/Resources/config/validation')) {
$this->getValidatorMappingFilesFromDir($dir, $files);
$container->addResource(new DirectoryResource($dir));
}
}
}
Expand Down Expand Up @@ -1202,23 +1194,21 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
$dirname = $bundle['path'];

if (is_file($file = $dirname.'/Resources/config/serialization.xml')) {
if ($container->fileExists($file = $dirname.'/Resources/config/serialization.xml', false)) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file));
$definition->setPublic(false);

$serializerLoaders[] = $definition;
$container->addResource(new FileResource($file));
}

if (is_file($file = $dirname.'/Resources/config/serialization.yml')) {
if ($container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file));
$definition->setPublic(false);

$serializerLoaders[] = $definition;
$container->addResource(new FileResource($file));
}

if (is_dir($dir = $dirname.'/Resources/config/serialization')) {
if ($container->fileExists($dir = $dirname.'/Resources/config/serialization')) {
foreach (Finder::create()->followLinks()->files()->in($dir)->name('*.xml') as $file) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getPathname()));
$definition->setPublic(false);
Expand All @@ -1231,8 +1221,6 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder

$serializerLoaders[] = $definition;
}

$container->addResource(new DirectoryResource($dir));
}
}

Expand Down
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Bundle\TwigBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Resource\FileExistenceResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
Expand Down Expand Up @@ -108,10 +107,9 @@ public function load(array $configs, ContainerBuilder $container)
}
}

if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) {
if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/views', false)) {
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir));
}
$container->addResource(new FileExistenceResource($dir));

if (!empty($config['globals'])) {
$def = $container->getDefinition('twig');
Expand Down Expand Up @@ -164,15 +162,13 @@ private function getBundleHierarchy(ContainerBuilder $container)
);
}

if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views')) {
if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views', false)) {
$bundleHierarchy[$name]['paths'][] = $dir;
}
$container->addResource(new FileExistenceResource($dir));

if (is_dir($dir = $bundle['path'].'/Resources/views')) {
if ($container->fileExists($dir = $bundle['path'].'/Resources/views', false)) {
$bundleHierarchy[$name]['paths'][] = $dir;
}
$container->addResource(new FileExistenceResource($dir));

if (null === $bundle['parent']) {
continue;
Expand Down
5 changes: 4 additions & 1 deletion src/Symfony/Bundle/TwigBundle/composer.json
Expand Up @@ -26,7 +26,7 @@
"require-dev": {
"symfony/asset": "~2.8|~3.0",
"symfony/stopwatch": "~2.8|~3.0",
"symfony/dependency-injection": "~2.8|~3.0",
"symfony/dependency-injection": "~3.3",
"symfony/expression-language": "~2.8|~3.0",
"symfony/finder": "~2.8|~3.0",
"symfony/form": "~2.8|~3.0",
Expand All @@ -36,6 +36,9 @@
"symfony/framework-bundle": "^3.2.2",
"doctrine/annotations": "~1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.3"
},
"autoload": {
"psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" },
"exclude-from-classmap": [
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/DependencyInjection/CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
3.3.0
-----

* added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence
* deprecated autowiring-types, use aliases instead
* [EXPERIMENTAL] added support for getter-injection
* added support for omitting the factory class name in a service definition if the definition class is set
Expand Down
38 changes: 38 additions & 0 deletions src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Expand Up @@ -25,6 +25,8 @@
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Config\Resource\FileExistenceResource;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
Expand Down Expand Up @@ -1321,6 +1323,42 @@ public static function getServiceConditionals($value)
return $services;
}

/**
* Checks whether the requested file or directory exists and registers the result for resource tracking.
*
* @param string $path The file or directory path for which to check the existence
* @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed,
* it will be used as pattern for tracking contents of the requested directory
*
* @return bool
*
* @final
*/
public function fileExists($path, $trackContents = true)
{
$exists = file_exists($path);

if (!$this->trackResources) {
return $exists;
}

if (!$exists) {
$this->addResource(new FileExistenceResource($path));

return $exists;
}

if ($trackContents) {
if (is_file($path)) {
$this->addResource(new FileResource($path));
} else {
$this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null));
}
}

return $exists;
}

/**
* Retrieves the currently set proxy instantiator or instantiates one.
*
Expand Down
Expand Up @@ -15,6 +15,7 @@
require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
Expand Down Expand Up @@ -682,6 +683,25 @@ public function testResources()
$this->assertEquals(array(), $container->getResources());
}

public function testFileExists()
{
$container = new ContainerBuilder();
$a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml');
$b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml');
$c = new DirectoryResource($dir = dirname($b));

$this->assertTrue($container->fileExists((string) $a) && $container->fileExists((string) $b) && $container->fileExists($dir));

$resources = array();
foreach ($container->getResources() as $resource) {
if (false === strpos($resource, '.php')) {
$resources[] = $resource;
}
}

$this->assertEquals(array($a, $b, $c), $resources, '->getResources() returns an array of resources read for the current configuration');
}

public function testExtension()
{
$container = new ContainerBuilder();
Expand Down

0 comments on commit 35a49fb

Please sign in to comment.