PageRenderTime 69ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/twig/twig/lib/Twig/Node/Expression/Call.php

https://gitlab.com/cuza/Clinic_Recods
PHP | 253 lines | 211 code | 33 blank | 9 comment | 56 complexity | bf1c280733aa21573dfeba087f885092 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) 2012 Fabien Potencier
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
  11. {
  12. protected function compileCallable(Twig_Compiler $compiler)
  13. {
  14. $closingParenthesis = false;
  15. if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
  16. if (is_string($callable)) {
  17. $compiler->raw($callable);
  18. } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
  19. $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
  20. } else {
  21. $type = ucfirst($this->getAttribute('type'));
  22. $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
  23. $closingParenthesis = true;
  24. }
  25. } else {
  26. $compiler->raw($this->getAttribute('thing')->compile());
  27. }
  28. $this->compileArguments($compiler);
  29. if ($closingParenthesis) {
  30. $compiler->raw(')');
  31. }
  32. }
  33. protected function compileArguments(Twig_Compiler $compiler)
  34. {
  35. $compiler->raw('(');
  36. $first = true;
  37. if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
  38. $compiler->raw('$this->env');
  39. $first = false;
  40. }
  41. if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
  42. if (!$first) {
  43. $compiler->raw(', ');
  44. }
  45. $compiler->raw('$context');
  46. $first = false;
  47. }
  48. if ($this->hasAttribute('arguments')) {
  49. foreach ($this->getAttribute('arguments') as $argument) {
  50. if (!$first) {
  51. $compiler->raw(', ');
  52. }
  53. $compiler->string($argument);
  54. $first = false;
  55. }
  56. }
  57. if ($this->hasNode('node')) {
  58. if (!$first) {
  59. $compiler->raw(', ');
  60. }
  61. $compiler->subcompile($this->getNode('node'));
  62. $first = false;
  63. }
  64. if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
  65. $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
  66. $arguments = $this->getArguments($callable, $this->getNode('arguments'));
  67. foreach ($arguments as $node) {
  68. if (!$first) {
  69. $compiler->raw(', ');
  70. }
  71. $compiler->subcompile($node);
  72. $first = false;
  73. }
  74. }
  75. $compiler->raw(')');
  76. }
  77. protected function getArguments($callable, $arguments)
  78. {
  79. $callType = $this->getAttribute('type');
  80. $callName = $this->getAttribute('name');
  81. $parameters = array();
  82. $named = false;
  83. foreach ($arguments as $name => $node) {
  84. if (!is_int($name)) {
  85. $named = true;
  86. $name = $this->normalizeName($name);
  87. } elseif ($named) {
  88. throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName));
  89. }
  90. $parameters[$name] = $node;
  91. }
  92. $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
  93. if (!$named && !$isVariadic) {
  94. return $parameters;
  95. }
  96. if (!$callable) {
  97. if ($named) {
  98. $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
  99. } else {
  100. $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
  101. }
  102. throw new LogicException($message);
  103. }
  104. // manage named arguments
  105. $callableParameters = $this->getCallableParameters($callable, $isVariadic);
  106. $arguments = array();
  107. $names = array();
  108. $missingArguments = array();
  109. $optionalArguments = array();
  110. $pos = 0;
  111. foreach ($callableParameters as $callableParameter) {
  112. $names[] = $name = $this->normalizeName($callableParameter->name);
  113. if (array_key_exists($name, $parameters)) {
  114. if (array_key_exists($pos, $parameters)) {
  115. throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
  116. }
  117. if (!empty($missingArguments)) {
  118. throw new Twig_Error_Syntax(sprintf(
  119. '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".',
  120. $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
  121. );
  122. }
  123. $arguments = array_merge($arguments, $optionalArguments);
  124. $arguments[] = $parameters[$name];
  125. unset($parameters[$name]);
  126. $optionalArguments = array();
  127. } elseif (array_key_exists($pos, $parameters)) {
  128. $arguments = array_merge($arguments, $optionalArguments);
  129. $arguments[] = $parameters[$pos];
  130. unset($parameters[$pos]);
  131. $optionalArguments = array();
  132. ++$pos;
  133. } elseif ($callableParameter->isDefaultValueAvailable()) {
  134. $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
  135. } elseif ($callableParameter->isOptional()) {
  136. if (empty($parameters)) {
  137. break;
  138. } else {
  139. $missingArguments[] = $name;
  140. }
  141. } else {
  142. throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
  143. }
  144. }
  145. if ($isVariadic) {
  146. $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
  147. foreach ($parameters as $key => $value) {
  148. if (is_int($key)) {
  149. $arbitraryArguments->addElement($value);
  150. } else {
  151. $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
  152. }
  153. unset($parameters[$key]);
  154. }
  155. if ($arbitraryArguments->count()) {
  156. $arguments = array_merge($arguments, $optionalArguments);
  157. $arguments[] = $arbitraryArguments;
  158. }
  159. }
  160. if (!empty($parameters)) {
  161. $unknownParameter = null;
  162. foreach ($parameters as $parameter) {
  163. if ($parameter instanceof Twig_Node) {
  164. $unknownParameter = $parameter;
  165. break;
  166. }
  167. }
  168. throw new Twig_Error_Syntax(sprintf(
  169. 'Unknown argument%s "%s" for %s "%s(%s)".',
  170. count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
  171. ), $unknownParameter ? $unknownParameter->getLine() : -1);
  172. }
  173. return $arguments;
  174. }
  175. protected function normalizeName($name)
  176. {
  177. return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
  178. }
  179. private function getCallableParameters($callable, $isVariadic)
  180. {
  181. if (is_array($callable)) {
  182. $r = new ReflectionMethod($callable[0], $callable[1]);
  183. } elseif (is_object($callable) && !$callable instanceof Closure) {
  184. $r = new ReflectionObject($callable);
  185. $r = $r->getMethod('__invoke');
  186. } elseif (is_string($callable) && false !== strpos($callable, '::')) {
  187. $r = new ReflectionMethod($callable);
  188. } else {
  189. $r = new ReflectionFunction($callable);
  190. }
  191. $parameters = $r->getParameters();
  192. if ($this->hasNode('node')) {
  193. array_shift($parameters);
  194. }
  195. if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
  196. array_shift($parameters);
  197. }
  198. if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
  199. array_shift($parameters);
  200. }
  201. if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
  202. foreach ($this->getAttribute('arguments') as $argument) {
  203. array_shift($parameters);
  204. }
  205. }
  206. if ($isVariadic) {
  207. $argument = end($parameters);
  208. if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
  209. array_pop($parameters);
  210. } else {
  211. $callableName = $r->name;
  212. if ($r->getDeclaringClass()) {
  213. $callableName = $r->getDeclaringClass()->name.'::'.$callableName;
  214. }
  215. 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')));
  216. }
  217. }
  218. return $parameters;
  219. }
  220. }