Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
CheckReferenceValidityPass.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\DependencyInjection\Compiler;
013
014 use Symfony\Component\DependencyInjection\Definition;
015 use Symfony\Component\DependencyInjection\ContainerInterface;
016 use Symfony\Component\DependencyInjection\Reference;
017 use Symfony\Component\DependencyInjection\ContainerBuilder;
018 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
019 use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
020 use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
021
022 /**
023 * Checks the validity of references
024 *
025 * The following checks are performed by this pass:
026 * - target definitions are not abstract
027 * - target definitions are of equal or wider scope
028 * - target definitions are in the same scope hierarchy
029 *
030 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
031 */
032 class CheckReferenceValidityPass implements CompilerPassInterface
033 {
034 private $container;
035 private $currentId;
036 private $currentDefinition;
037 private $currentScope;
038 private $currentScopeAncestors;
039 private $currentScopeChildren;
040
041 /**
042 * Processes the ContainerBuilder to validate References.
043 *
044 * @param ContainerBuilder $container
045 */
046 public function process(ContainerBuilder $container)
047 {
048 $this->container = $container;
049
050 $children = $this->container->getScopeChildren();
051 $ancestors = array();
052
053 $scopes = $this->container->getScopes();
054 foreach ($scopes as $name => $parent) {
055 $ancestors[$name] = array($parent);
056
057 while (isset($scopes[$parent])) {
058 $ancestors[$name][] = $parent = $scopes[$parent];
059 }
060 }
061
062 foreach ($container->getDefinitions() as $id => $definition) {
063 if ($definition->isSynthetic() || $definition->isAbstract()) {
064 continue;
065 }
066
067 $this->currentId = $id;
068 $this->currentDefinition = $definition;
069 $this->currentScope = $scope = $definition->getScope();
070
071 if (ContainerInterface::SCOPE_CONTAINER === $scope) {
072 $this->currentScopeChildren = array_keys($scopes);
073 $this->currentScopeAncestors = array();
074 } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
075 $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
076 $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
077 }
078
079 $this->validateReferences($definition->getArguments());
080 $this->validateReferences($definition->getMethodCalls());
081 $this->validateReferences($definition->getProperties());
082 }
083 }
084
085 /**
086 * Validates an array of References.
087 *
088 * @param array $arguments An array of Reference objects
089 *
090 * @throws RuntimeException when there is a reference to an abstract definition.
091 */
092 private function validateReferences(array $arguments)
093 {
094 foreach ($arguments as $argument) {
095 if (is_array($argument)) {
096 $this->validateReferences($argument);
097 } elseif ($argument instanceof Reference) {
098 $targetDefinition = $this->getDefinition((string) $argument);
099
100 if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
101 throw new RuntimeException(sprintf(
102 'The definition "%s" has a reference to an abstract definition "%s". '
103 .'Abstract definitions cannot be the target of references.',
104 $this->currentId,
105 $argument
106 ));
107 }
108
109 $this->validateScope($argument, $targetDefinition);
110 }
111 }
112 }
113
114 /**
115 * Validates the scope of a single Reference.
116 *
117 * @param Reference $reference
118 * @param Definition $definition
119 *
120 * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
121 * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
122 */
123 private function validateScope(Reference $reference, Definition $definition = null)
124 {
125 if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
126 return;
127 }
128
129 if (!$reference->isStrict()) {
130 return;
131 }
132
133 if (null === $definition) {
134 return;
135 }
136
137 if ($this->currentScope === $scope = $definition->getScope()) {
138 return;
139 }
140
141 $id = (string) $reference;
142
143 if (in_array($scope, $this->currentScopeChildren, true)) {
144 throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
145 }
146
147 if (!in_array($scope, $this->currentScopeAncestors, true)) {
148 throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
149 }
150 }
151
152 /**
153 * Returns the Definition given an id.
154 *
155 * @param string $id Definition identifier
156 *
157 * @return Definition
158 */
159 private function getDefinition($id)
160 {
161 if (!$this->container->hasDefinition($id)) {
162 return;
163 }
164
165 return $this->container->getDefinition($id);
166 }
167 }
168