Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
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 $currentScope;
037 private $currentScopeAncestors;
038 private $currentScopeChildren;
039
040 /**
041 * Processes the ContainerBuilder to validate References.
042 *
043 * @param ContainerBuilder $container
044 */
045 public function process(ContainerBuilder $container)
046 {
047 $this->container = $container;
048
049 $children = $this->container->getScopeChildren(false);
050 $ancestors = array();
051
052 $scopes = $this->container->getScopes(false);
053 foreach ($scopes as $name => $parent) {
054 $ancestors[$name] = array($parent);
055
056 while (isset($scopes[$parent])) {
057 $ancestors[$name][] = $parent = $scopes[$parent];
058 }
059 }
060
061 foreach ($container->getDefinitions() as $id => $definition) {
062 if ($definition->isSynthetic() || $definition->isAbstract()) {
063 continue;
064 }
065
066 $this->currentId = $id;
067 $this->currentScope = $scope = $definition->getScope(false);
068
069 if (ContainerInterface::SCOPE_CONTAINER === $scope) {
070 $this->currentScopeChildren = array_keys($scopes);
071 $this->currentScopeAncestors = array();
072 } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
073 $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
074 $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
075 }
076
077 $this->validateReferences($definition->getArguments());
078 $this->validateReferences($definition->getMethodCalls());
079 $this->validateReferences($definition->getProperties());
080 }
081 }
082
083 /**
084 * Validates an array of References.
085 *
086 * @param array $arguments An array of Reference objects
087 *
088 * @throws RuntimeException when there is a reference to an abstract definition.
089 */
090 private function validateReferences(array $arguments)
091 {
092 foreach ($arguments as $argument) {
093 if (is_array($argument)) {
094 $this->validateReferences($argument);
095 } elseif ($argument instanceof Reference) {
096 $targetDefinition = $this->getDefinition((string) $argument);
097
098 if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
099 throw new RuntimeException(sprintf(
100 'The definition "%s" has a reference to an abstract definition "%s". '
101 .'Abstract definitions cannot be the target of references.',
102 $this->currentId,
103 $argument
104 ));
105 }
106
107 $this->validateScope($argument, $targetDefinition);
108 }
109 }
110 }
111
112 /**
113 * Validates the scope of a single Reference.
114 *
115 * @param Reference $reference
116 * @param Definition $definition
117 *
118 * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
119 * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
120 */
121 private function validateScope(Reference $reference, Definition $definition = null)
122 {
123 if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
124 return;
125 }
126
127 if (!$reference->isStrict(false)) {
128 return;
129 }
130
131 if (null === $definition) {
132 return;
133 }
134
135 if ($this->currentScope === $scope = $definition->getScope(false)) {
136 return;
137 }
138
139 $id = (string) $reference;
140
141 if (in_array($scope, $this->currentScopeChildren, true)) {
142 throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
143 }
144
145 if (!in_array($scope, $this->currentScopeAncestors, true)) {
146 throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
147 }
148 }
149
150 /**
151 * Returns the Definition given an id.
152 *
153 * @param string $id Definition identifier
154 *
155 * @return Definition
156 */
157 private function getDefinition($id)
158 {
159 if (!$this->container->hasDefinition($id)) {
160 return;
161 }
162
163 return $this->container->getDefinition($id);
164 }
165 }
166