/**
  * Get a ReflectionProperty deeply.
  * 
  * @param \ReflectionClass $class
  * @param string $dottedReference The given dotted reference
  * @return mixed Usually a \ReflectionProperty. If the dotted reference falls into
  *					an associative array property, we will return "<array>"
  */
 private function getDeepProperty(\ReflectionClass $class, $dottedReference)
 {
     $originalClass = $class;
     $fields = $this->pathParser->parse($dottedReference);
     $fieldCount = count($fields);
     $property = null;
     $className = $originalClass->getName();
     $properties = array();
     foreach ($fields as $i => $field) {
         if ($className == '<array>') {
             $properties[] = '<array>';
             continue;
         }
         $isPrimitive = $this->isPrimitiveType($className);
         // Cannot traverse into primitive types (it is impossible for this
         // to happen on first iteration)
         if ($isPrimitive) {
             throw new \InvalidArgumentException("Cannot traverse into primitive type {$className} " . "to satisfy reference '{$field->field}' " . "of full reference '{$dottedReference}'");
         }
         $currentClass = new \ReflectionClass($className);
         $property = $currentClass->getProperty($field->field);
         $properties[] = $property;
         // We're done? We'll return $property at the end.
         if ($i + 1 >= $fieldCount) {
             break;
         }
         $className = $this->reflector->getTypeFromProperty($property);
         if (!$className) {
             throw new \InvalidArgumentException("Failed to reflect on field reference '{$dottedReference}' of class {$originalClass->getName()}");
         }
     }
     return $properties;
 }
Esempio n. 2
0
 /**
  * Get a ReflectionProperty deeply.
  * 
  * @param \ReflectionClass $class
  * @param string $dottedReference The given dotted reference
  * @return mixed Usually a \ReflectionProperty. If the dotted reference falls into
  *					an associative array property, we will return "<array>"
  */
 private function getDeepProperty(\ReflectionClass $class, $dottedReference)
 {
     $pathParser = new PathParser();
     $reflector = new Reflector();
     $originalClass = $class;
     $fields = $pathParser->parse($dottedReference);
     $fieldCount = count($fields);
     $reflectionField = null;
     $className = $originalClass->getName();
     $reflectionFields = array();
     foreach ($fields as $i => $field) {
         if ($className == '<array>') {
             $reflectionFields[] = '<array>';
             continue;
         }
         // Cannot traverse into primitive types (it is impossible for this
         // to happen on first iteration)
         if ($reflector->isPrimitiveType($className)) {
             throw new \InvalidArgumentException("Cannot traverse into primitive type {$className} " . "to satisfy reference '{$field->field}' " . "of full reference '{$dottedReference}'");
         }
         $currentClass = new \ReflectionClass($className);
         $fieldName = $field->field;
         $methodName = "get{$fieldName}";
         if ($currentClass->hasMethod($methodName)) {
             //Method
             $reflectionField = $currentClass->getMethod($methodName);
         } else {
             if ($currentClass->hasProperty($fieldName)) {
                 //Property
                 $reflectionField = $currentClass->getProperty($fieldName);
             } else {
                 throw new \Exception("Could get property \"{$fieldName}\" in the class \"{$className}\" it either does not exist or does not have a getter.");
             }
         }
         $reflectionFields[] = $reflectionField;
         // We're done? We'll return $property at the end.
         if ($i + 1 >= $fieldCount) {
             break;
         }
         $className = $reflector->getType($reflectionField);
         if (!$className) {
             throw new \InvalidArgumentException("Failed to reflect on field reference '{$dottedReference}' of class {$originalClass->getName()}");
         }
     }
     return $reflectionFields;
 }
Esempio n. 3
0
 /**
  * Gets the value of the property named $field on $instance.
  * 
  * @param object $instance
  * @param mixed $field A string path (see PathParser), an array of path field reference objects,
  *						or a single field reference object. 
  * @return mixed
  * @throws \Exception Thrown if no such field/property exists
  */
 private function get($instance, $field)
 {
     if (is_string($field)) {
         $field = $this->pathParser->parse($field);
     }
     if (is_array($field)) {
         $path = $field;
     } else {
         $path = array($field);
     }
     // Walk the path to the penultimate object.
     $contextObject =& $instance;
     foreach ($path as $i => $item) {
         if ($i + 1 >= count($path)) {
             continue;
         }
         $contextObject = $this->get($contextObject, $item);
     }
     $fieldName = $path[count($path) - 1]->field;
     // Arrays...
     if (is_array($contextObject)) {
         if (!isset($contextObject[$fieldName])) {
             return null;
         }
         return $contextObject[$fieldName];
     }
     // Doesn't exist _yet_!
     if (is_null($contextObject)) {
         return null;
     }
     // Various ways of retrieving an object field...
     if (is_object($contextObject)) {
         $methodName = "get{$fieldName}";
         if (method_exists($contextObject, $methodName)) {
             return $contextObject->{$methodName}();
         } else {
             if (property_exists($contextObject, $fieldName)) {
                 return $contextObject->{$fieldName};
             } else {
                 throw new \InvalidArgumentException("No such property {$fieldName} on object of class " . get_class($contextObject));
             }
         }
     }
     throw new \InvalidArgumentException("Cannot set field {$fieldName} on a non-object:\nPath trace: " . print_r($path, true) . "\nObject trace: " . print_r($contextObject, true));
 }