[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of Twig. 5 * 6 * (c) 2012 Fabien Potencier 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 abstract class Twig_Node_Expression_Call extends Twig_Node_Expression 12 { 13 protected function compileCallable(Twig_Compiler $compiler) 14 { 15 $closingParenthesis = false; 16 if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) { 17 if (is_string($callable)) { 18 $compiler->raw($callable); 19 } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) { 20 $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1])); 21 } else { 22 $type = ucfirst($this->getAttribute('type')); 23 $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); 24 $closingParenthesis = true; 25 } 26 } else { 27 $compiler->raw($this->getAttribute('thing')->compile()); 28 } 29 30 $this->compileArguments($compiler); 31 32 if ($closingParenthesis) { 33 $compiler->raw(')'); 34 } 35 } 36 37 protected function compileArguments(Twig_Compiler $compiler) 38 { 39 $compiler->raw('('); 40 41 $first = true; 42 43 if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { 44 $compiler->raw('$this->env'); 45 $first = false; 46 } 47 48 if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { 49 if (!$first) { 50 $compiler->raw(', '); 51 } 52 $compiler->raw('$context'); 53 $first = false; 54 } 55 56 if ($this->hasAttribute('arguments')) { 57 foreach ($this->getAttribute('arguments') as $argument) { 58 if (!$first) { 59 $compiler->raw(', '); 60 } 61 $compiler->string($argument); 62 $first = false; 63 } 64 } 65 66 if ($this->hasNode('node')) { 67 if (!$first) { 68 $compiler->raw(', '); 69 } 70 $compiler->subcompile($this->getNode('node')); 71 $first = false; 72 } 73 74 if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) { 75 $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; 76 77 $arguments = $this->getArguments($callable, $this->getNode('arguments')); 78 79 foreach ($arguments as $node) { 80 if (!$first) { 81 $compiler->raw(', '); 82 } 83 $compiler->subcompile($node); 84 $first = false; 85 } 86 } 87 88 $compiler->raw(')'); 89 } 90 91 protected function getArguments($callable, $arguments) 92 { 93 $callType = $this->getAttribute('type'); 94 $callName = $this->getAttribute('name'); 95 96 $parameters = array(); 97 $named = false; 98 foreach ($arguments as $name => $node) { 99 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |