Esempio n. 1
0
 protected function accessValue(array $parts, InspectedValue $inspection, $inspect = false)
 {
     for ($max = count($parts) - 1, $i = 0; $i <= $max; $i++) {
         // Method call (with arguments):
         if (is_array($parts[$i])) {
             if (!is_object($inspection->value)) {
                 if ($inspection->useDefaultValue) {
                     $inspection->value = $inspection->defaultValue;
                     return $inspection;
                 }
                 if ($this->accessPolicy == self::ACCESS_POLICY_THROW_EXCEPTION) {
                     throw new ExpressionValueAccessException(sprintf('Cannot call method "%s" on non-object within path "%s"', $parts[$i][0], ExpressionContext::flattenPath($parts)));
                 }
                 $inspection->value = NULL;
                 return $inspection;
             }
             $methodName = $parts[$i][0];
             if (!method_exists($inspection->value, $methodName)) {
                 if ($inspection->useDefaultValue) {
                     $inspection->value = $inspection->defaultValue;
                     return $inspection;
                 }
                 if ($this->accessPolicy == self::ACCESS_POLICY_THROW_EXCEPTION) {
                     throw new ExpressionValueAccessException(sprintf('Method "%s" is not defined for object of type %s within path "%s"', $methodName, get_class($inspection->value), ExpressionContext::flattenPath($parts)));
                 }
                 $inspection->value = NULL;
                 return $inspection;
             }
             if (!is_callable([$inspection->value, $methodName])) {
                 if ($inspection->useDefaultValue) {
                     $inspection->value = $inspection->defaultValue;
                     return $inspection;
                 }
                 if ($this->accessPolicy == self::ACCESS_POLICY_THROW_EXCEPTION) {
                     throw new ExpressionValueAccessException(sprintf('Cannot call invisible method "%s" on object of type %s within path "%s"', $methodName, get_class($inspection->value), ExpressionContext::flattenPath($parts)));
                 }
                 $inspection->value = NULL;
                 return $inspection;
             }
             if ($inspect && $i === $max) {
                 $inspection->container = $inspection->value;
                 $inspection->inspect = true;
                 $inspection->name = $methodName;
                 $inspection->resolved = true;
                 $inspection->method = new \ReflectionMethod(get_class($inspection->value), $methodName);
             }
             $inspection->value = $inspection->value->{$methodName}(...$parts[$i][1]);
             if ($i !== $max) {
                 continue;
             }
             return $inspection;
         }
         // Specialized handling of "this".
         if ($parts[$i] === 'this') {
             $inspection->value = $this;
             if ($i !== $max) {
                 continue;
             }
             return $inspection;
         }
         // Standard property access using resolvers.
         $inspection->container = $inspection->value;
         $inspection->name = $parts[$i];
         $inspection->inspect = $inspect && $i === $max;
         // PHP array
         if (is_array($inspection->value)) {
             if (array_key_exists($parts[$i], $inspection->value)) {
                 $inspection->value = $inspection->value[$parts[$i]];
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
         }
         // Specialized access via interface.
         if ($inspection->value instanceof ExpressionAccessInterface) {
             if ($inspection->value->resolveExpressionValue($inspection)) {
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
         }
         // ArrayAccess:
         if ($inspection->value instanceof \ArrayAccess) {
             if ($inspection->value->offsetExists($parts[$i])) {
                 $inspection->value = $inspection->value->offsetGet($parts[$i]);
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
         }
         // Access via fields and properties.
         if (is_object($inspection->value)) {
             if (array_key_exists($parts[$i], (array) $inspection->value)) {
                 $inspection->field = new \ReflectionProperty(get_class($inspection->value), $parts[$i]);
                 $inspection->value = $inspection->value->{$parts[$i]};
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
             if (method_exists($inspection->value, 'get' . $parts[$i])) {
                 $inspection->method = new \ReflectionMethod(get_class($inspection->value), 'get' . $parts[$i]);
                 $inspection->value = $inspection->value->{'get' . $parts[$i]}();
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
             if (method_exists($inspection->value, 'is' . $parts[$i])) {
                 $inspection->method = new \ReflectionMethod(get_class($inspection->value), 'is' . $parts[$i]);
                 $inspection->value = $inspection->value->{'is' . $parts[$i]}();
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
             if (method_exists($inspection->value, '__get')) {
                 $inspection->value = $inspection->value->{$parts[$i]};
                 if ($i !== $max) {
                     continue;
                 }
                 $inspection->resolved = true;
                 return $inspection;
             }
         }
         if ($inspection->useDefaultValue) {
             $inspection->value = $inspection->defaultValue;
             return $inspection;
         }
         if ($this->accessPolicy == self::ACCESS_POLICY_RETURN_NULL) {
             $inspection->value = NULL;
             return $inspection;
         }
         $type = is_object($inspection->value) ? get_class($inspection->value) : gettype($inspection->value);
         throw new ExpressionValueAccessException(sprintf('Unable to access property "%s" of %s within path "%s"', $parts[$i], $type, ExpressionContext::flattenPath($parts)));
     }
     throw new ExpressionValueAccessException('Cannot access property without a name');
 }
 /**
  * {@inheritdoc}
  */
 public function createContext($data = NULL) : ExpressionContextInterface
 {
     $context = new ExpressionContext($this, $data);
     $context->setAccessPolicy($this->defaultAccessPolicy);
     return $context;
 }