/** * @test */ public function getValueReturnsValueOfAPrivatePropertyEvenIfItIsAnObject() { $reflectionProperty = new \TYPO3\Flow\Reflection\PropertyReflection(__CLASS__, 'privateProperty'); $this->protectedProperty = new \ArrayObject(array('1', '2', '3')); $this->assertEquals($this->privateProperty, $reflectionProperty->getValue($this), 'ReflectionProperty->getValue($this) did not return the object of our private property.'); $this->privateProperty = $this; $this->assertSame($this, $reflectionProperty->getValue($this), 'ReflectionProperty->getValue($this) did not return the reference to $this.'); }
/** * Gets a property of a given object or array. * This is an internal method that does only limited type checking for performance reasons. * If you can't make sure that $subject is either of type array or object and $propertyName of type string you should use getProperty() instead. * * @param mixed $subject Object or array to get the property from * @param string $propertyName name of the property to retrieve * @param boolean $forceDirectAccess directly access property using reflection(!) * @param boolean $propertyExists (by reference) will be set to TRUE if the specified property exists and is gettable * @return mixed Value of the property * @throws \TYPO3\Flow\Reflection\Exception\PropertyNotAccessibleException * @see getProperty() */ protected static function getPropertyInternal($subject, $propertyName, $forceDirectAccess, &$propertyExists) { if ($subject === NULL) { return NULL; } if (is_array($subject)) { if (array_key_exists($propertyName, $subject)) { $propertyExists = TRUE; return $subject[$propertyName]; } return NULL; } elseif (!is_object($subject)) { return NULL; } $propertyExists = TRUE; if ($forceDirectAccess === TRUE) { if (property_exists(get_class($subject), $propertyName)) { $propertyReflection = new \TYPO3\Flow\Reflection\PropertyReflection(get_class($subject), $propertyName); return $propertyReflection->getValue($subject); } elseif (property_exists($subject, $propertyName)) { return $subject->{$propertyName}; } else { throw new \TYPO3\Flow\Reflection\Exception\PropertyNotAccessibleException('The property "' . $propertyName . '" on the subject does not exist.', 1302855001); } } if ($subject instanceof \stdClass) { if (array_key_exists($propertyName, get_object_vars($subject))) { return $subject->{$propertyName}; } else { $propertyExists = FALSE; return NULL; } } $class = get_class($subject); $identifier = $class . '|' . $propertyName; if (!isset(self::$propertyGetterCache[$identifier])) { self::$propertyGetterCache[$identifier] = array(); $getterMethodName = 'get' . ucfirst($propertyName); if (is_callable(array($subject, $getterMethodName))) { self::$propertyGetterCache[$identifier]['accessorMethod'] = $getterMethodName; } else { $getterMethodName = 'is' . ucfirst($propertyName); if (is_callable(array($subject, $getterMethodName))) { self::$propertyGetterCache[$identifier]['accessorMethod'] = $getterMethodName; } else { if (!$subject instanceof \ArrayAccess && array_key_exists($propertyName, get_object_vars($subject))) { self::$propertyGetterCache[$identifier]['publicProperty'] = $propertyName; } } } } if (isset(self::$propertyGetterCache[$identifier]['accessorMethod'])) { $method = self::$propertyGetterCache[$identifier]['accessorMethod']; return $subject->{$method}(); } elseif (isset(self::$propertyGetterCache[$identifier]['publicProperty'])) { return $subject->{$propertyName}; } if ($subject instanceof \ArrayAccess && !$subject instanceof \SplObjectStorage) { if (isset($subject[$propertyName])) { return $subject[$propertyName]; } } $propertyExists = FALSE; return NULL; }
/** * Serializes an object as property array. * * @param object $object The object to store in the registry * @param boolean $isTopLevelItem Internal flag for managing the recursion * @return array The property array */ public function serializeObjectAsPropertyArray($object, $isTopLevelItem = true) { if ($isTopLevelItem) { $this->objectReferences = new \SplObjectStorage(); } $this->objectReferences->attach($object); $className = get_class($object); $propertyArray = array(); foreach ($this->reflectionService->getClassPropertyNames($className) as $propertyName) { if ($this->reflectionService->isPropertyTaggedWith($className, $propertyName, 'transient')) { continue; } $propertyReflection = new \TYPO3\Flow\Reflection\PropertyReflection($className, $propertyName); $propertyValue = $propertyReflection->getValue($object); if (is_object($propertyValue) && $propertyValue instanceof \TYPO3\Flow\Object\DependencyInjection\DependencyProxy) { continue; } if (is_object($propertyValue) && isset($this->objectReferences[$propertyValue])) { $propertyArray[$propertyName][self::TYPE] = 'object'; $propertyArray[$propertyName][self::VALUE] = \spl_object_hash($propertyValue); continue; } $propertyClassName = is_object($propertyValue) ? get_class($propertyValue) : ''; if ($propertyClassName === 'SplObjectStorage') { $propertyArray[$propertyName][self::TYPE] = 'SplObjectStorage'; $propertyArray[$propertyName][self::VALUE] = array(); foreach ($propertyValue as $storedObject) { $propertyArray[$propertyName][self::VALUE][] = spl_object_hash($storedObject); $this->serializeObjectAsPropertyArray($storedObject, false); } } elseif (is_object($propertyValue) && $propertyValue instanceof \Doctrine\Common\Collections\Collection) { $propertyArray[$propertyName][self::TYPE] = 'Collection'; $propertyArray[$propertyName][self::CLASSNAME] = get_class($propertyValue); foreach ($propertyValue as $storedObject) { $propertyArray[$propertyName][self::VALUE][] = spl_object_hash($storedObject); $this->serializeObjectAsPropertyArray($storedObject, false); } } elseif (is_object($propertyValue) && $propertyValue instanceof \ArrayObject) { $propertyArray[$propertyName][self::TYPE] = 'ArrayObject'; $propertyArray[$propertyName][self::VALUE] = $this->buildStorageArrayForArrayProperty($propertyValue->getArrayCopy()); } elseif (is_object($propertyValue) && $this->persistenceManager->isNewObject($propertyValue) === false && ($this->reflectionService->isClassAnnotatedWith($propertyClassName, \TYPO3\Flow\Annotations\Entity::class) || $this->reflectionService->isClassAnnotatedWith($propertyClassName, \TYPO3\Flow\Annotations\ValueObject::class) || $this->reflectionService->isClassAnnotatedWith($propertyClassName, 'Doctrine\\ORM\\Mapping\\Entity'))) { $propertyArray[$propertyName][self::TYPE] = 'persistenceObject'; $propertyArray[$propertyName][self::VALUE] = get_class($propertyValue) . ':' . $this->persistenceManager->getIdentifierByObject($propertyValue); } elseif (is_object($propertyValue)) { $propertyObjectName = $this->objectManager->getObjectNameByClassName($propertyClassName); if ($this->objectManager->getScope($propertyObjectName) === \TYPO3\Flow\Object\Configuration\Configuration::SCOPE_SINGLETON) { continue; } $propertyArray[$propertyName][self::TYPE] = 'object'; $propertyArray[$propertyName][self::VALUE] = spl_object_hash($propertyValue); $this->serializeObjectAsPropertyArray($propertyValue, false); } elseif (is_array($propertyValue)) { $propertyArray[$propertyName][self::TYPE] = 'array'; $propertyArray[$propertyName][self::VALUE] = $this->buildStorageArrayForArrayProperty($propertyValue); } else { $propertyArray[$propertyName][self::TYPE] = 'simple'; $propertyArray[$propertyName][self::VALUE] = $propertyValue; } } $this->objectsAsArray[spl_object_hash($object)] = array(self::CLASSNAME => $className, self::PROPERTIES => $propertyArray); if ($isTopLevelItem) { return $this->objectsAsArray; } }