Added the Search API Synonym module to deal specifically with licence and license...
[yaffs-website] / vendor / symfony / dependency-injection / Loader / FileLoader.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\DependencyInjection\Loader;
13
14 use Symfony\Component\Config\FileLocatorInterface;
15 use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
16 use Symfony\Component\Config\Resource\GlobResource;
17 use Symfony\Component\DependencyInjection\ChildDefinition;
18 use Symfony\Component\DependencyInjection\ContainerBuilder;
19 use Symfony\Component\DependencyInjection\Definition;
20 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
21
22 /**
23  * FileLoader is the abstract class used by all built-in loaders that are file based.
24  *
25  * @author Fabien Potencier <fabien@symfony.com>
26  */
27 abstract class FileLoader extends BaseFileLoader
28 {
29     protected $container;
30     protected $isLoadingInstanceof = false;
31     protected $instanceof = array();
32
33     public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
34     {
35         $this->container = $container;
36
37         parent::__construct($locator);
38     }
39
40     /**
41      * Registers a set of classes as services using PSR-4 for discovery.
42      *
43      * @param Definition $prototype A definition to use as template
44      * @param string     $namespace The namespace prefix of classes in the scanned directory
45      * @param string     $resource  The directory to look for classes, glob-patterns allowed
46      * @param string     $exclude   A globed path of files to exclude
47      */
48     public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null)
49     {
50         if ('\\' !== substr($namespace, -1)) {
51             throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": %s.', $namespace));
52         }
53         if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) {
54             throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: %s.', $namespace));
55         }
56
57         $classes = $this->findClasses($namespace, $resource, $exclude);
58         // prepare for deep cloning
59         $serializedPrototype = serialize($prototype);
60         $interfaces = array();
61         $singlyImplemented = array();
62
63         foreach ($classes as $class => $errorMessage) {
64             if (interface_exists($class, false)) {
65                 $interfaces[] = $class;
66             } else {
67                 $this->setDefinition($class, $definition = unserialize($serializedPrototype));
68                 if (null !== $errorMessage) {
69                     $definition->addError($errorMessage);
70
71                     continue;
72                 }
73                 foreach (class_implements($class, false) as $interface) {
74                     $singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class;
75                 }
76             }
77         }
78         foreach ($interfaces as $interface) {
79             if (!empty($singlyImplemented[$interface])) {
80                 $this->container->setAlias($interface, $singlyImplemented[$interface])
81                     ->setPublic(false);
82             }
83         }
84     }
85
86     /**
87      * Registers a definition in the container with its instanceof-conditionals.
88      *
89      * @param string     $id
90      * @param Definition $definition
91      */
92     protected function setDefinition($id, Definition $definition)
93     {
94         if ($this->isLoadingInstanceof) {
95             if (!$definition instanceof ChildDefinition) {
96                 throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, \get_class($definition)));
97             }
98             $this->instanceof[$id] = $definition;
99         } else {
100             $this->container->setDefinition($id, $definition instanceof ChildDefinition ? $definition : $definition->setInstanceofConditionals($this->instanceof));
101         }
102     }
103
104     private function findClasses($namespace, $pattern, $excludePattern)
105     {
106         $parameterBag = $this->container->getParameterBag();
107
108         $excludePaths = array();
109         $excludePrefix = null;
110         if ($excludePattern) {
111             $excludePattern = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePattern));
112             foreach ($this->glob($excludePattern, true, $resource) as $path => $info) {
113                 if (null === $excludePrefix) {
114                     $excludePrefix = $resource->getPrefix();
115                 }
116
117                 // normalize Windows slashes
118                 $excludePaths[str_replace('\\', '/', $path)] = true;
119             }
120         }
121
122         $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern));
123         $classes = array();
124         $extRegexp = \defined('HHVM_VERSION') ? '/\\.(?:php|hh)$/' : '/\\.php$/';
125         $prefixLen = null;
126         foreach ($this->glob($pattern, true, $resource) as $path => $info) {
127             if (null === $prefixLen) {
128                 $prefixLen = \strlen($resource->getPrefix());
129
130                 if ($excludePrefix && 0 !== strpos($excludePrefix, $resource->getPrefix())) {
131                     throw new InvalidArgumentException(sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s)', $namespace, $excludePattern, $pattern));
132                 }
133             }
134
135             if (isset($excludePaths[str_replace('\\', '/', $path)])) {
136                 continue;
137             }
138
139             if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) {
140                 continue;
141             }
142             $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, -\strlen($m[0]))), '\\');
143
144             if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) {
145                 continue;
146             }
147
148             try {
149                 $r = $this->container->getReflectionClass($class);
150             } catch (\ReflectionException $e) {
151                 $classes[$class] = sprintf(
152                     'While discovering services from namespace "%s", an error was thrown when processing the class "%s": "%s".',
153                     $namespace,
154                     $class,
155                     $e->getMessage()
156                 );
157                 continue;
158             }
159             // check to make sure the expected class exists
160             if (!$r) {
161                 throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
162             }
163
164             if ($r->isInstantiable() || $r->isInterface()) {
165                 $classes[$class] = null;
166             }
167         }
168
169         // track only for new & removed files
170         if ($resource instanceof GlobResource) {
171             $this->container->addResource($resource);
172         } else {
173             foreach ($resource as $path) {
174                 $this->container->fileExists($path, false);
175             }
176         }
177
178         return $classes;
179     }
180 }