You are here

abstract class Twig_Node_Expression_Call in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/twig/twig/lib/Twig/Node/Expression/Call.php \Twig_Node_Expression_Call

Hierarchy

Expanded class hierarchy of Twig_Node_Expression_Call

File

vendor/twig/twig/lib/Twig/Node/Expression/Call.php, line 11

View source
abstract class Twig_Node_Expression_Call extends Twig_Node_Expression {
  protected function compileCallable(Twig_Compiler $compiler) {
    $closingParenthesis = false;
    if ($this
      ->hasAttribute('callable') && ($callable = $this
      ->getAttribute('callable'))) {
      if (is_string($callable)) {
        $compiler
          ->raw($callable);
      }
      elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
        $compiler
          ->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]
          ->getName(), $callable[1]));
      }
      else {
        $type = ucfirst($this
          ->getAttribute('type'));
        $compiler
          ->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this
          ->getAttribute('name')));
        $closingParenthesis = true;
      }
    }
    else {
      $compiler
        ->raw($this
        ->getAttribute('thing')
        ->compile());
    }
    $this
      ->compileArguments($compiler);
    if ($closingParenthesis) {
      $compiler
        ->raw(')');
    }
  }
  protected function compileArguments(Twig_Compiler $compiler) {
    $compiler
      ->raw('(');
    $first = true;
    if ($this
      ->hasAttribute('needs_environment') && $this
      ->getAttribute('needs_environment')) {
      $compiler
        ->raw('$this->env');
      $first = false;
    }
    if ($this
      ->hasAttribute('needs_context') && $this
      ->getAttribute('needs_context')) {
      if (!$first) {
        $compiler
          ->raw(', ');
      }
      $compiler
        ->raw('$context');
      $first = false;
    }
    if ($this
      ->hasAttribute('arguments')) {
      foreach ($this
        ->getAttribute('arguments') as $argument) {
        if (!$first) {
          $compiler
            ->raw(', ');
        }
        $compiler
          ->string($argument);
        $first = false;
      }
    }
    if ($this
      ->hasNode('node')) {
      if (!$first) {
        $compiler
          ->raw(', ');
      }
      $compiler
        ->subcompile($this
        ->getNode('node'));
      $first = false;
    }
    if ($this
      ->hasNode('arguments') && null !== $this
      ->getNode('arguments')) {
      $callable = $this
        ->hasAttribute('callable') ? $this
        ->getAttribute('callable') : null;
      $arguments = $this
        ->getArguments($callable, $this
        ->getNode('arguments'));
      foreach ($arguments as $node) {
        if (!$first) {
          $compiler
            ->raw(', ');
        }
        $compiler
          ->subcompile($node);
        $first = false;
      }
    }
    $compiler
      ->raw(')');
  }
  protected function getArguments($callable, $arguments) {
    $callType = $this
      ->getAttribute('type');
    $callName = $this
      ->getAttribute('name');
    $parameters = array();
    $named = false;
    foreach ($arguments as $name => $node) {
      if (!is_int($name)) {
        $named = true;
        $name = $this
          ->normalizeName($name);
      }
      elseif ($named) {
        throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName));
      }
      $parameters[$name] = $node;
    }
    $isVariadic = $this
      ->hasAttribute('is_variadic') && $this
      ->getAttribute('is_variadic');
    if (!$named && !$isVariadic) {
      return $parameters;
    }
    if (!$callable) {
      if ($named) {
        $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
      }
      else {
        $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
      }
      throw new LogicException($message);
    }

    // manage named arguments
    if (is_array($callable)) {
      $r = new ReflectionMethod($callable[0], $callable[1]);
    }
    elseif (is_object($callable) && !$callable instanceof Closure) {
      $r = new ReflectionObject($callable);
      $r = $r
        ->getMethod('__invoke');
    }
    elseif (is_string($callable) && false !== strpos($callable, '::')) {
      $r = new ReflectionMethod($callable);
    }
    else {
      $r = new ReflectionFunction($callable);
    }
    $definition = $r
      ->getParameters();
    if ($this
      ->hasNode('node')) {
      array_shift($definition);
    }
    if ($this
      ->hasAttribute('needs_environment') && $this
      ->getAttribute('needs_environment')) {
      array_shift($definition);
    }
    if ($this
      ->hasAttribute('needs_context') && $this
      ->getAttribute('needs_context')) {
      array_shift($definition);
    }
    if ($this
      ->hasAttribute('arguments') && null !== $this
      ->getAttribute('arguments')) {
      foreach ($this
        ->getAttribute('arguments') as $argument) {
        array_shift($definition);
      }
    }
    if ($isVariadic) {
      $argument = end($definition);
      if ($argument && $argument
        ->isArray() && $argument
        ->isDefaultValueAvailable() && array() === $argument
        ->getDefaultValue()) {
        array_pop($definition);
      }
      else {
        $callableName = $r->name;
        if ($r
          ->getDeclaringClass()) {
          $callableName = $r
            ->getDeclaringClass()->name . '::' . $callableName;
        }
        throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $callType, $callName));
      }
    }
    $arguments = array();
    $names = array();
    $missingArguments = array();
    $optionalArguments = array();
    $pos = 0;
    foreach ($definition as $param) {
      $names[] = $name = $this
        ->normalizeName($param->name);
      if (array_key_exists($name, $parameters)) {
        if (array_key_exists($pos, $parameters)) {
          throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
        }
        if (!empty($missingArguments)) {
          throw new Twig_Error_Syntax(sprintf('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".', $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)));
        }
        $arguments = array_merge($arguments, $optionalArguments);
        $arguments[] = $parameters[$name];
        unset($parameters[$name]);
        $optionalArguments = array();
      }
      elseif (array_key_exists($pos, $parameters)) {
        $arguments = array_merge($arguments, $optionalArguments);
        $arguments[] = $parameters[$pos];
        unset($parameters[$pos]);
        $optionalArguments = array();
        ++$pos;
      }
      elseif ($param
        ->isDefaultValueAvailable()) {
        $optionalArguments[] = new Twig_Node_Expression_Constant($param
          ->getDefaultValue(), -1);
      }
      elseif ($param
        ->isOptional()) {
        if (empty($parameters)) {
          break;
        }
        else {
          $missingArguments[] = $name;
        }
      }
      else {
        throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
      }
    }
    if ($isVariadic) {
      $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
      foreach ($parameters as $key => $value) {
        if (is_int($key)) {
          $arbitraryArguments
            ->addElement($value);
        }
        else {
          $arbitraryArguments
            ->addElement($value, new Twig_Node_Expression_Constant($key, -1));
        }
        unset($parameters[$key]);
      }
      if ($arbitraryArguments
        ->count()) {
        $arguments = array_merge($arguments, $optionalArguments);
        $arguments[] = $arbitraryArguments;
      }
    }
    if (!empty($parameters)) {
      $unknownParameter = null;
      foreach ($parameters as $parameter) {
        if ($parameter instanceof Twig_Node) {
          $unknownParameter = $parameter;
          break;
        }
      }
      throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s(%s)".', count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)), $unknownParameter ? $unknownParameter
        ->getLine() : -1);
    }
    return $arguments;
  }
  protected function normalizeName($name) {
    return strtolower(preg_replace(array(
      '/([A-Z]+)([A-Z][a-z])/',
      '/([a-z\\d])([A-Z])/',
    ), array(
      '\\1_\\2',
      '\\1_\\2',
    ), $name));
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Twig_Node::$attributes protected property
Twig_Node::$lineno protected property
Twig_Node::$nodes protected property
Twig_Node::$tag protected property
Twig_Node::compile public function Compiles the node to PHP. Overrides Twig_NodeInterface::compile 36
Twig_Node::count public function
Twig_Node::getAttribute public function Gets an attribute value by name.
Twig_Node::getIterator public function
Twig_Node::getLine public function Overrides Twig_NodeInterface::getLine
Twig_Node::getNode public function Gets a node by name.
Twig_Node::getNodeTag public function Overrides Twig_NodeInterface::getNodeTag
Twig_Node::hasAttribute public function Returns true if the attribute is defined.
Twig_Node::hasNode public function Returns true if the node with the given name exists.
Twig_Node::removeAttribute public function Removes an attribute by name.
Twig_Node::removeNode public function Removes a node by name.
Twig_Node::setAttribute public function Sets an attribute by name to a value.
Twig_Node::setNode public function Sets a node.
Twig_Node::toXml Deprecated public function
Twig_Node::__construct public function Constructor. 36
Twig_Node::__toString public function
Twig_Node_Expression_Call::compileArguments protected function
Twig_Node_Expression_Call::compileCallable protected function
Twig_Node_Expression_Call::getArguments protected function 1
Twig_Node_Expression_Call::normalizeName protected function