public function getMapping($key) { if (isset($this->mappings[$key])) { $property = $this->mappings[$key]; if (isset($this->object->properties[$property])) { return $this->object->properties[$property]->value; } return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($this->object->object, $property); } if (isset($this->object->properties[$key])) { return $this->object->properties[$key]->value; } # $getter = "get" . ucfirst($key); # if(method_exists($this->object->object, $getter)) # return call_user_func(array($this->object->object, $getter)); return false; }
/** * Load the property value to be used for validation. * * In case the object is a doctrine proxy, we need to load the real instance first. * * @param object $object * @param string $propertyName * @return mixed */ protected function getPropertyValue($object, $propertyName) { if ($object instanceof \Doctrine\ORM\Proxy\Proxy) { $reflectionLoadMethod = new \ReflectionMethod($object, '__load'); $reflectionLoadMethod->setAccessible(TRUE); $reflectionLoadMethod->invoke($object); } if (\TYPO3\FLOW3\Reflection\ObjectAccess::isPropertyGettable($object, $propertyName)) { return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName); } else { return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName, TRUE); } }
/** * @test */ public function getPropertyCanAccessPropertiesOfAnArray() { $array = array('key' => 'value'); $expected = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($array, 'key'); $this->assertEquals($expected, 'value', 'getProperty does not work with Array property.'); }
/** * Registers an object which has been created or cloned during this request. * * The given object must contain the FLOW3_Persistence_Identifier property, thus * the PersistenceMagicInterface type hint. A "new" object does not necessarily * have to be known by any repository or be persisted in the end. * * Objects registered with this method must be known to the getObjectByIdentifier() * method. * * @param \TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface $object The new object to register * @return void */ public function registerNewObject(\TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface $object) { $identifier = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, 'FLOW3_Persistence_Identifier', TRUE); $this->newObjects[$identifier] = $object; }
/** * Check the property value for allowed types and throw exceptions for * unsupported types. * * @param object $object The object with the property to check * @param string $propertyName The name of the property to check * @param array $propertyMetaData Property metadata * @return mixed The value of the property * @throws \TYPO3\FLOW3\Persistence\Generic\Exception\UnexpectedTypeException * @throws \TYPO3\FLOW3\Persistence\Exception * @throws \TYPO3\FLOW3\Persistence\Exception\IllegalObjectTypeException * @api */ protected function checkPropertyValue($object, $propertyName, array $propertyMetaData) { $propertyValue = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName, TRUE); $propertyType = $propertyMetaData['type']; if ($propertyType === 'ArrayObject') { throw new \TYPO3\FLOW3\Persistence\Exception('ArrayObject properties are not supported - missing feature?!?', 1283524355); } if (is_object($propertyValue)) { if ($propertyType === 'object') { if (!$propertyValue instanceof \TYPO3\FLOW3\Persistence\Aspect\PersistenceMagicInterface) { throw new \TYPO3\FLOW3\Persistence\Exception\IllegalObjectTypeException('Property of generic type object holds "' . get_class($propertyValue) . '", which is not persistable (no entity or value object), in ' . get_class($object) . '::' . $propertyName, 1283531761); } } elseif (!$propertyValue instanceof $propertyType) { throw new \TYPO3\FLOW3\Persistence\Generic\Exception\UnexpectedTypeException('Expected property of type ' . $propertyType . ', but got ' . get_class($propertyValue) . ' for ' . get_class($object) . '::' . $propertyName, 1244465558); } } elseif ($propertyValue !== NULL && $propertyType !== $this->getType($propertyValue)) { throw new \TYPO3\FLOW3\Persistence\Generic\Exception\UnexpectedTypeException('Expected property of type ' . $propertyType . ', but got ' . gettype($propertyValue) . ' for ' . get_class($object) . '::' . $propertyName, 1244465559); } return $propertyValue; }
/** * Traverses the given object structure in order to transform it into an * array structure. * * @param object $object Object to traverse * @param mixed $configuration Configuration for transforming the given object or NULL * @return array Object structure as an aray */ protected function transformObject($object, $configuration) { if ($object instanceof \DateTime) { return $object->format('Y-m-d\\TH:i:s'); } else { $propertyNames = \TYPO3\FLOW3\Reflection\ObjectAccess::getGettablePropertyNames($object); $propertiesToRender = array(); foreach ($propertyNames as $propertyName) { if (isset($configuration['_only']) && is_array($configuration['_only']) && !in_array($propertyName, $configuration['_only'])) { continue; } if (isset($configuration['_exclude']) && is_array($configuration['_exclude']) && in_array($propertyName, $configuration['_exclude'])) { continue; } $propertyValue = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName); if (!is_array($propertyValue) && !is_object($propertyValue)) { $propertiesToRender[$propertyName] = $propertyValue; } elseif (isset($configuration['_descend']) && array_key_exists($propertyName, $configuration['_descend'])) { $propertiesToRender[$propertyName] = $this->transformValue($propertyValue, $configuration['_descend'][$propertyName]); } } if (isset($configuration['_exposeObjectIdentifier']) && $configuration['_exposeObjectIdentifier'] === TRUE) { if (isset($configuration['_exposedObjectIdentifierKey']) && strlen($configuration['_exposedObjectIdentifierKey']) > 0) { $identityKey = $configuration['_exposedObjectIdentifierKey']; } else { $identityKey = '__identity'; } $propertiesToRender[$identityKey] = $this->persistenceManager->getIdentifierByObject($object); } return $propertiesToRender; } }
/** * Renders a dump of the given object * * @param object $object * @param integer $level * @param boolean $renderProperties * @param boolean $plaintext * @param boolean $ansiColors * @return string */ protected static function renderObjectDump($object, $level, $renderProperties = TRUE, $plaintext = FALSE, $ansiColors = FALSE) { $dump = ''; $scope = ''; $additionalAttributes = ''; if ($object instanceof \Doctrine\Common\Collections\Collection) { return self::renderArrayDump(\Doctrine\Common\Util\Debug::export($object, 12), $level, $plaintext, $ansiColors); } // Objects returned from Doctrine's Debug::export function are stdClass with special properties: try { $objectIdentifier = ObjectAccess::getProperty($object, 'FLOW3_Persistence_Identifier', TRUE); } catch (\TYPO3\FLOW3\Reflection\Exception\PropertyNotAccessibleException $exception) { $objectIdentifier = spl_object_hash($object); } $className = $object instanceof \stdClass && isset($object->__CLASS__) ? $object->__CLASS__ : get_class($object); if (preg_match(self::$blacklistedClassNames, $className) !== 0 || isset(self::$renderedObjects[$objectIdentifier])) { $renderProperties = FALSE; } self::$renderedObjects[$objectIdentifier] = TRUE; if (self::$objectManager !== NULL) { $objectName = self::$objectManager->getObjectNameByClassName(get_class($object)); if ($objectName !== FALSE) { switch (self::$objectManager->getScope($objectName)) { case \TYPO3\FLOW3\Object\Configuration\Configuration::SCOPE_PROTOTYPE: $scope = 'prototype'; break; case \TYPO3\FLOW3\Object\Configuration\Configuration::SCOPE_SINGLETON: $scope = 'singleton'; break; case \TYPO3\FLOW3\Object\Configuration\Configuration::SCOPE_SESSION: $scope = 'session'; break; } } else { $additionalAttributes .= ' debug-unregistered'; } } if ($renderProperties === TRUE && !$plaintext) { if ($scope === '') { $scope = 'prototype'; } $scope .= '<a id="o' . $objectIdentifier . '"></a>'; } if ($plaintext) { $dump .= $className; $dump .= $scope !== '' ? ' ' . self::ansiEscapeWrap($scope, '44;37', $ansiColors) : ''; } else { $dump .= '<span class="debug-object' . $additionalAttributes . '" title="' . $objectIdentifier . '">' . $className . '</span>'; $dump .= $scope !== '' ? '<span class="debug-scope">' . $scope . '</span>' : ''; } if (property_exists($object, 'FLOW3_Persistence_Identifier')) { $persistenceIdentifier = $objectIdentifier; $persistenceType = 'persistable'; } else { $persistenceIdentifier = 'unknown'; $persistenceType = 'object'; } if ($plaintext) { $dump .= ' ' . self::ansiEscapeWrap($persistenceType, '42;37', $ansiColors); } else { $dump .= '<span class="debug-ptype" title="' . $persistenceIdentifier . '">' . $persistenceType . '</span>'; } if ($object instanceof \TYPO3\FLOW3\Object\Proxy\ProxyInterface || isset($object->__IS_PROXY__) && $object->__IS_PROXY__ === TRUE) { if ($plaintext) { $dump .= ' ' . self::ansiEscapeWrap('proxy', '41;37', $ansiColors); } else { $dump .= '<span class="debug-proxy" title="' . $className . '">proxy</span>'; } } if ($renderProperties === TRUE) { if ($object instanceof \SplObjectStorage) { $dump .= ' (' . (count($object) ?: 'empty') . ')'; foreach ($object as $value) { $dump .= chr(10); $dump .= str_repeat(' ', $level); $dump .= self::renderObjectDump($value, 0, FALSE, $plaintext, $ansiColors); } } else { $classReflection = new \ReflectionClass($className); $properties = $classReflection->getProperties(); foreach ($properties as $property) { if (preg_match(self::$blacklistedPropertyNames, $property->getName())) { continue; } $dump .= chr(10); $dump .= str_repeat(' ', $level) . ($plaintext ? '' : '<span class="debug-property">') . self::ansiEscapeWrap($property->getName(), '36', $ansiColors) . ($plaintext ? '' : '</span>') . ' => '; $property->setAccessible(TRUE); $value = $property->getValue($object); if (is_array($value)) { $dump .= self::renderDump($value, $level + 1, $plaintext, $ansiColors); } elseif (is_object($value)) { $dump .= self::renderObjectDump($value, $level + 1, TRUE, $plaintext, $ansiColors); } else { $dump .= self::renderDump($value, $level, $plaintext, $ansiColors); } } } } elseif (isset(self::$renderedObjects[$objectIdentifier])) { if (!$plaintext) { $dump = '<a href="#o' . $objectIdentifier . '" onclick="document.location.hash=\'#o' . $objectIdentifier . '\'; return false;" class="debug-seeabove" title="see above">' . $dump . '</a>'; } } return $dump; }
public function getStringByProperties($source) { $properties = $this->getProperties($source); $strings = array(); $count = 0; foreach ($properties as $key => $meta) { if ($count > 3) { break; } if ($key !== "FLOW3_Persistence_Identifier") { if (\TYPO3\FLOW3\Reflection\ObjectAccess::isPropertyGettable($source, $key)) { $value = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($source, $key); if (is_string($value)) { $strings[] = $value; $count++; } elseif (is_object($value) && $this->nestingLevel < 3) { $this->nestingLevel++; $string = $this->convertFrom($value, "string"); if (!is_null($string)) { $strings[] = $string; $count++; } $this->nestingLevel--; } } } } if (!empty($strings)) { return implode(", ", $strings); } return false; }
/** * After returning advice, generates the value hash for the object * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void * @FLOW3\Before("classAnnotatedWith(TYPO3\FLOW3\Annotations\ValueObject) && method(.*->__construct())") */ public function generateValueHash(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $hashSource = get_class($proxy); if (property_exists($proxy, 'FLOW3_Persistence_Identifier')) { $hashSource .= \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($proxy, 'FLOW3_Persistence_Identifier', TRUE); } foreach ($joinPoint->getMethodArguments() as $argumentValue) { if (is_array($argumentValue)) { $hashSource .= $this->useIgBinary === TRUE ? igbinary_serialize($argumentValue) : serialize($argumentValue); } elseif (!is_object($argumentValue)) { $hashSource .= $argumentValue; } elseif (property_exists($argumentValue, 'FLOW3_Persistence_Identifier')) { $hashSource .= \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($argumentValue, 'FLOW3_Persistence_Identifier', TRUE); } elseif ($argumentValue instanceof \DateTime) { $hashSource .= $argumentValue->getTimestamp(); } } $proxy = $joinPoint->getProxy(); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($proxy, 'FLOW3_Persistence_Identifier', sha1($hashSource), TRUE); }
public function toArray() { $array = array(); $properties = get_class_vars(get_class($this)); foreach ($properties as $property => $value) { $value = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($this, $property); if (is_object($value) && is_callable(array($value, "__toString"))) { $array[$property] = strval($value); } else { $array[$property] = $value; } } return $array; }
/** * Returns the identifier for the given object either from * the session, if the object was registered, or from the object * itself using a special uuid property or the internal * properties set by AOP. * * Note: this returns an UUID even if the object has not been persisted * in case of AOP-managed entities. Use isNewObject() if you need * to distinguish those cases. * * @param object $object * @return string * @api */ public function getIdentifierByObject($object) { if ($this->hasObject($object)) { return $this->objectMap[$object]; } $idPropertyNames = $this->reflectionService->getPropertyNamesByTag(get_class($object), 'id'); if (count($idPropertyNames) === 1) { $idPropertyName = $idPropertyNames[0]; return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $idPropertyName, TRUE); } elseif (property_exists($object, 'FLOW3_Persistence_Identifier')) { return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, 'FLOW3_Persistence_Identifier', TRUE); } return NULL; }
/** * Wrap the $content identified by $node with the needed markup for * the backend. * $parameters can be used to further pass parameters to the content element. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node * @param string $typoscriptPath * @param string $content * @param boolean $isPage * @return string */ public function wrapContentObject(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node, $typoscriptPath, $content, $isPage = FALSE) { $contentType = $node->getContentType(); $tagBuilder = new \TYPO3\Fluid\Core\ViewHelper\TagBuilder('div'); $tagBuilder->forceClosingTag(TRUE); if (!$node->isRemoved()) { $tagBuilder->setContent($content); } if (!$isPage) { $cssClasses = array('t3-contentelement'); $cssClasses[] = str_replace(array(':', '.'), '-', strtolower($contentType->getName())); if ($node->isHidden()) { $cssClasses[] = 't3-contentelement-hidden'; } if ($node->isRemoved()) { $cssClasses[] = 't3-contentelement-removed'; } $tagBuilder->addAttribute('class', implode(' ', $cssClasses)); $tagBuilder->addAttribute('id', 'c' . $node->getIdentifier()); } try { $this->accessDecisionManager->decideOnResource('TYPO3_TYPO3_Backend_BackendController'); } catch (\TYPO3\FLOW3\Security\Exception\AccessDeniedException $e) { return $tagBuilder->render(); } $tagBuilder->addAttribute('typeof', 'typo3:' . $contentType->getName()); $tagBuilder->addAttribute('about', $node->getContextPath()); $this->addScriptTag($tagBuilder, '__workspacename', $node->getWorkspace()->getName()); $this->addScriptTag($tagBuilder, '_removed', $node->isRemoved() ? 'true' : 'false', 'boolean'); $this->addScriptTag($tagBuilder, '_typoscriptPath', $typoscriptPath); foreach ($contentType->getProperties() as $propertyName => $propertyConfiguration) { $dataType = isset($propertyConfiguration['type']) ? $propertyConfiguration['type'] : 'string'; if ($propertyName[0] === '_') { $propertyValue = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($node, substr($propertyName, 1)); } else { $propertyValue = $node->getProperty($propertyName); } // Serialize boolean values to String if (isset($propertyConfiguration['type']) && $propertyConfiguration['type'] === 'boolean') { $propertyValue = $propertyValue ? 'true' : 'false'; } // Serialize date values to String if ($propertyValue !== NULL && isset($propertyConfiguration['type']) && $propertyConfiguration['type'] === 'date') { $propertyValue = $propertyValue->format('Y-m-d'); } // Serialize objects to JSON strings if (is_object($propertyValue) && $propertyValue !== NULL && isset($propertyConfiguration['type']) && $this->objectManager->isRegistered($propertyConfiguration['type'])) { $gettableProperties = \TYPO3\FLOW3\Reflection\ObjectAccess::getGettableProperties($propertyValue); $convertedProperties = array(); foreach ($gettableProperties as $key => $value) { if (is_object($value)) { $entityIdentifier = $this->persistenceManager->getIdentifierByObject($value); if ($entityIdentifier !== NULL) { $value = $entityIdentifier; } } $convertedProperties[$key] = $value; } $propertyValue = json_encode($convertedProperties); $dataType = 'jsonEncoded'; } $this->addScriptTag($tagBuilder, $propertyName, $propertyValue, $dataType); } if (!$isPage) { // add CSS classes $this->addScriptTag($tagBuilder, '__contenttype', $contentType->getName()); } else { $tagBuilder->addAttribute('id', 't3-page-metainformation'); $tagBuilder->addAttribute('data-__sitename', $this->nodeRepository->getContext()->getCurrentSite()->getName()); $tagBuilder->addAttribute('data-__siteroot', sprintf('/sites/%s@%s', $this->nodeRepository->getContext()->getCurrentSite()->getNodeName(), $this->nodeRepository->getContext()->getWorkspace()->getName())); } return $tagBuilder->render(); }
/** * MongoDB does not do partial updates, thus this method always collects the * full set of properties. * Value objects are always inlined. * * @param string $identifier The object's identifier * @param object $object The object to work on * @param array $properties The properties to collect (as per class schema) * @param boolean $dirty A dirty flag that is passed by reference and set to TRUE if a dirty property was found * @author Karsten Dambekalns <*****@*****.**> * @author Christopher Hlubek <*****@*****.**> */ protected function collectProperties($identifier, $object, array $properties, &$dirty) { $propertyData = array(); foreach ($properties as $propertyName => $propertyMetaData) { $this->checkPropertyValue($object, $propertyName, $propertyMetaData); $propertyValue = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName, TRUE); if ($this->persistenceSession->isDirty($object, $propertyName)) { $dirty = TRUE; } $this->flattenValue($identifier, $object, $propertyName, $propertyMetaData, $propertyData); } return $propertyData; }
/** * returns the specified property of the mixed variable * * @param string $property * @param string $mixed * @return void * @author Marc Neuhaus */ public function getValue($property, $mixed) { $value = null; try { if (is_object($mixed) || is_array($mixed)) { $value = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($mixed, $property); } } catch (\TYPO3\FLOW3\Reflection\Exception\PropertyNotAccessibleException $e) { var_dump($e); } return $value; }
/** * Returns the (internal) identifier for the object, if it is known to the * backend. Otherwise NULL is returned. * * Note: this returns an identifier even if the object has not been * persisted in case of AOP-managed entities. Use isNewObject() if you need * to distinguish those cases. * * @param object $object * @return mixed The identifier for the object if it is known, or NULL * @api * @todo improve try/catch block */ public function getIdentifierByObject($object) { if ($this->entityManager->contains($object)) { try { return current($this->entityManager->getUnitOfWork()->getEntityIdentifier($object)); } catch (\Doctrine\ORM\ORMException $e) { return NULL; } } elseif (property_exists($object, 'FLOW3_Persistence_Identifier')) { return \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($object, 'FLOW3_Persistence_Identifier', TRUE); } else { return NULL; } }