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 |
Call.php
001 <?php
002
003 /*
004 * This file is part of Twig.
005 *
006 * (c) 2012 Fabien Potencier
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011 abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
012 {
013 protected function compileCallable(Twig_Compiler $compiler)
014 {
015 $closingParenthesis = false;
016 if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
017 if (is_string($callable)) {
018 $compiler->raw($callable);
019 } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
020 $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
021 } else {
022 $type = ucfirst($this->getAttribute('type'));
023 $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
024 $closingParenthesis = true;
025 }
026 } else {
027 $compiler->raw($this->getAttribute('thing')->compile());
028 }
029
030 $this->compileArguments($compiler);
031
032 if ($closingParenthesis) {
033 $compiler->raw(')');
034 }
035 }
036
037 protected function compileArguments(Twig_Compiler $compiler)
038 {
039 $compiler->raw('(');
040
041 $first = true;
042
043 if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
044 $compiler->raw('$this->env');
045 $first = false;
046 }
047
048 if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
049 if (!$first) {
050 $compiler->raw(', ');
051 }
052 $compiler->raw('$context');
053 $first = false;
054 }
055
056 if ($this->hasAttribute('arguments')) {
057 foreach ($this->getAttribute('arguments') as $argument) {
058 if (!$first) {
059 $compiler->raw(', ');
060 }
061 $compiler->string($argument);
062 $first = false;
063 }
064 }
065
066 if ($this->hasNode('node')) {
067 if (!$first) {
068 $compiler->raw(', ');
069 }
070 $compiler->subcompile($this->getNode('node'));
071 $first = false;
072 }
073
074 if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
075 $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
076
077 $arguments = $this->getArguments($callable, $this->getNode('arguments'));
078
079 foreach ($arguments as $node) {
080 if (!$first) {
081 $compiler->raw(', ');
082 }
083 $compiler->subcompile($node);
084 $first = false;
085 }
086 }
087
088 $compiler->raw(')');
089 }
090
091 protected function getArguments($callable, $arguments)
092 {
093 $callType = $this->getAttribute('type');
094 $callName = $this->getAttribute('name');
095
096 $parameters = array();
097 $named = false;
098 foreach ($arguments as $name => $node) {
099 if (!is_int($name)) {
100 $named = true;
101 $name = $this->normalizeName($name);
102 } elseif ($named) {
103 throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName));
104 }
105
106 $parameters[$name] = $node;
107 }
108
109 $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
110 if (!$named && !$isVariadic) {
111 return $parameters;
112 }
113
114 if (!$callable) {
115 if ($named) {
116 $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
117 } else {
118 $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
119 }
120
121 throw new LogicException($message);
122 }
123
124 // manage named arguments
125 $callableParameters = $this->getCallableParameters($callable, $isVariadic);
126 $arguments = array();
127 $names = array();
128 $missingArguments = array();
129 $optionalArguments = array();
130 $pos = 0;
131 foreach ($callableParameters as $callableParameter) {
132 $names[] = $name = $this->normalizeName($callableParameter->name);
133
134 if (array_key_exists($name, $parameters)) {
135 if (array_key_exists($pos, $parameters)) {
136 throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
137 }
138
139 if (!empty($missingArguments)) {
140 throw new Twig_Error_Syntax(sprintf(
141 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
142 $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
143 );
144 }
145
146 $arguments = array_merge($arguments, $optionalArguments);
147 $arguments[] = $parameters[$name];
148 unset($parameters[$name]);
149 $optionalArguments = array();
150 } elseif (array_key_exists($pos, $parameters)) {
151 $arguments = array_merge($arguments, $optionalArguments);
152 $arguments[] = $parameters[$pos];
153 unset($parameters[$pos]);
154 $optionalArguments = array();
155 ++$pos;
156 } elseif ($callableParameter->isDefaultValueAvailable()) {
157 $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
158 } elseif ($callableParameter->isOptional()) {
159 if (empty($parameters)) {
160 break;
161 } else {
162 $missingArguments[] = $name;
163 }
164 } else {
165 throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
166 }
167 }
168
169 if ($isVariadic) {
170 $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
171 foreach ($parameters as $key => $value) {
172 if (is_int($key)) {
173 $arbitraryArguments->addElement($value);
174 } else {
175 $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
176 }
177 unset($parameters[$key]);
178 }
179
180 if ($arbitraryArguments->count()) {
181 $arguments = array_merge($arguments, $optionalArguments);
182 $arguments[] = $arbitraryArguments;
183 }
184 }
185
186 if (!empty($parameters)) {
187 $unknownParameter = null;
188 foreach ($parameters as $parameter) {
189 if ($parameter instanceof Twig_Node) {
190 $unknownParameter = $parameter;
191 break;
192 }
193 }
194
195 throw new Twig_Error_Syntax(sprintf(
196 'Unknown argument%s "%s" for %s "%s(%s)".',
197 count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
198 ), $unknownParameter ? $unknownParameter->getLine() : -1);
199 }
200
201 return $arguments;
202 }
203
204 protected function normalizeName($name)
205 {
206 return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
207 }
208
209 private function getCallableParameters($callable, $isVariadic)
210 {
211 if (is_array($callable)) {
212 $r = new ReflectionMethod($callable[0], $callable[1]);
213 } elseif (is_object($callable) && !$callable instanceof Closure) {
214 $r = new ReflectionObject($callable);
215 $r = $r->getMethod('__invoke');
216 } elseif (is_string($callable) && false !== strpos($callable, '::')) {
217 $r = new ReflectionMethod($callable);
218 } else {
219 $r = new ReflectionFunction($callable);
220 }
221
222 $parameters = $r->getParameters();
223 if ($this->hasNode('node')) {
224 array_shift($parameters);
225 }
226 if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
227 array_shift($parameters);
228 }
229 if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
230 array_shift($parameters);
231 }
232 if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
233 foreach ($this->getAttribute('arguments') as $argument) {
234 array_shift($parameters);
235 }
236 }
237 if ($isVariadic) {
238 $argument = end($parameters);
239 if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
240 array_pop($parameters);
241 } else {
242 $callableName = $r->name;
243 if ($r instanceof ReflectionMethod) {
244 $callableName = $r->getDeclaringClass()->name.'::'.$callableName;
245 }
246
247 throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
248 }
249 }
250
251 return $parameters;
252 }
253 }
254