/** * @test */ public function convertFromUsesAppropriatePropertyPopulationMethodsInOrderConstructorSetterPublic() { $convertedObject = $this->converter->convertFrom('irrelevant', Fixtures\TestClass::class, ['propertyMeantForConstructorUsage' => 'theValue', 'propertyMeantForSetterUsage' => 'theValue', 'propertyMeantForPublicUsage' => 'theValue'], new PropertyMappingConfiguration()); $this->assertEquals('theValue set via Constructor', ObjectAccess::getProperty($convertedObject, 'propertyMeantForConstructorUsage', true)); $this->assertEquals('theValue set via Setter', ObjectAccess::getProperty($convertedObject, 'propertyMeantForSetterUsage', true)); $this->assertEquals('theValue', ObjectAccess::getProperty($convertedObject, 'propertyMeantForPublicUsage', true)); }
/** * Change the property on the given node. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { foreach ($node->getNodeType()->getProperties() as $propertyName => $propertyConfiguration) { if (isset($propertyConfiguration['type']) && in_array(trim($propertyConfiguration['type']), $this->getHandledObjectTypes())) { if (!isset($nodeProperties)) { $nodeRecordQuery = $this->entityManager->getConnection()->prepare('SELECT properties FROM typo3_typo3cr_domain_model_nodedata WHERE persistence_object_identifier=?'); $nodeRecordQuery->execute([$this->persistenceManager->getIdentifierByObject($node)]); $nodeRecord = $nodeRecordQuery->fetch(\PDO::FETCH_ASSOC); $nodeProperties = unserialize($nodeRecord['properties']); } if (!isset($nodeProperties[$propertyName]) || !is_object($nodeProperties[$propertyName])) { continue; } /** @var Asset $assetObject */ $assetObject = $nodeProperties[$propertyName]; $nodeProperties[$propertyName] = null; $stream = $assetObject->getResource()->getStream(); if ($stream === false) { continue; } fclose($stream); $objectType = TypeHandling::getTypeForValue($assetObject); $objectIdentifier = ObjectAccess::getProperty($assetObject, 'Persistence_Object_Identifier', true); $nodeProperties[$propertyName] = array('__flow_object_type' => $objectType, '__identifier' => $objectIdentifier); } } if (isset($nodeProperties)) { $nodeUpdateQuery = $this->entityManager->getConnection()->prepare('UPDATE typo3_typo3cr_domain_model_nodedata SET properties=? WHERE persistence_object_identifier=?'); $nodeUpdateQuery->execute([serialize($nodeProperties), $this->persistenceManager->getIdentifierByObject($node)]); } }
/** * @return void */ public function up() { $affectedViewHelperClassNames = array(); $allPathsAndFilenames = Files::readDirectoryRecursively($this->targetPackageData['path'], '.php', true); foreach ($allPathsAndFilenames as $pathAndFilename) { if (substr($pathAndFilename, -14) !== 'ViewHelper.php') { continue; } $fileContents = file_get_contents($pathAndFilename); $className = (new PhpAnalyzer($fileContents))->extractFullyQualifiedClassName(); if ($className === null) { $this->showWarning(sprintf('could not extract class name from file "%s"', $pathAndFilename)); continue; } /** @noinspection PhpIncludeInspection */ require_once $pathAndFilename; if (!class_exists($className)) { $this->showWarning(sprintf('could not load class "%s" extracted from file "%s"', $className, $pathAndFilename)); continue; } $instance = new $className(); $escapeOutput = ObjectAccess::getProperty($instance, 'escapeOutput', true); if ($escapeOutput !== null) { continue; } $affectedViewHelperClassNames[] = $className; $this->searchAndReplaceRegex('/\\R\\s*class[^\\{]+\\R?\\{(\\s*)(?=.*?\\})/s', '$0' . "\n\t" . '/**' . "\n\t" . ' * NOTE: This property has been introduced via code migration to ensure backwards-compatibility.' . "\n\t" . ' * @see AbstractViewHelper::isOutputEscapingEnabled()' . "\n\t" . ' * @var boolean' . "\n\t" . ' */' . "\n\t" . 'protected $escapeOutput = FALSE;$1', $pathAndFilename); } if ($affectedViewHelperClassNames !== array()) { $this->showWarning('Added "escapeOutput" property to following ViewHelpers:' . PHP_EOL . ' * ' . implode(PHP_EOL . ' * ', $affectedViewHelperClassNames) . PHP_EOL . PHP_EOL . 'If an affected ViewHelper does not render HTML output, you should set this property TRUE in order to ensure sanitization of the output!'); } $this->addWarningsForAffectedViewHelpers($this->targetPackageData['path']); }
/** * See the configuration in Testing/Objects.yaml * @test */ public function configuredObjectDWillGetAssignedObjectFWithCorrectlyConfiguredConstructorValue() { $instance = $this->objectManager->get(Fixtures\PrototypeClassD::class); /** @var $instanceE Fixtures\PrototypeClassE */ $instanceE = ObjectAccess::getProperty($instance, 'objectE', true); $this->assertEquals('The constructor set value', $instanceE->getNullValue()); }
/** * @test */ public function ignoredClassesCanBeOverwrittenBySettings() { $object = new ApplicationContext('Development'); $this->assertEquals(sprintf('%s prototype object', ApplicationContext::class), Debugger::renderDump($object, 10, true)); Debugger::clearState(); $currentConfiguration = ObjectAccess::getProperty($this->configurationManager, 'configurations', true); $configurationOverwrite['Settings']['Neos']['Flow']['error']['debugger']['ignoredClasses']['Neos\\\\Flow\\\\Core\\\\.*'] = false; $newConfiguration = Arrays::arrayMergeRecursiveOverrule($currentConfiguration, $configurationOverwrite); ObjectAccess::setProperty($this->configurationManager, 'configurations', $newConfiguration, true); $this->assertContains('rootContextString', Debugger::renderDump($object, 10, true)); }
/** * Returns TRUE if the given node is of the node type this filter expects. * * @param NodeData $node * @return boolean */ public function matches(NodeData $node) { if ($this->withSubTypes === true) { $nodeIsMatchingNodeType = $node->getNodeType()->isOfType($this->nodeTypeName); } else { // This is needed to get the raw string NodeType to prevent errors for NodeTypes that no longer exist. $nodeType = ObjectAccess::getProperty($node, 'nodeType', true); $nodeIsMatchingNodeType = $nodeType === $this->nodeTypeName; } if ($this->exclude === true) { return !$nodeIsMatchingNodeType; } return $nodeIsMatchingNodeType; }
/** * WARNING: If using this step definition, IT MUST RUN AS ABSOLUTELY FIRST STEP IN A SCENARIO! * * @Given /^I have the following policies:$/ */ public function iHaveTheFollowingPolicies($string) { if ($this->subProcess !== null) { // This check ensures that this statement is ran *before* a subprocess is opened; as the Policy.yaml // which is set here influences the Proxy Building Process. throw new \Exception('Step "I have the following policies:" must run as FIRST step in a scenario, because otherwise the proxy-classes are already built in the wrong manner!'); } self::$testingPolicyPathAndFilename = $this->environment->getPathToTemporaryDirectory() . 'Policy.yaml'; file_put_contents(self::$testingPolicyPathAndFilename, $string->getRaw()); $configurationManager = $this->objectManager->get(ConfigurationManager::class); $configurations = ObjectAccess::getProperty($configurationManager, 'configurations', true); unset($configurations[ConfigurationManager::CONFIGURATION_PROCESSING_TYPE_POLICY]); ObjectAccess::setProperty($configurationManager, 'configurations', $configurations, true); $policyService = $this->objectManager->get(PolicyService::class); ObjectAccess::setProperty($policyService, 'initialized', false, true); }
/** * @param JoinPointInterface $joinPoint * @param string $profilePath * @return ProfileInterface */ protected function profile(JoinPointInterface $joinPoint, $profilePath) { /** @var PaletteInterface $proxy */ $proxy = $joinPoint->getProxy(); try { $profile = ObjectAccess::getProperty($proxy, 'profile', TRUE); } catch (\Exception $exception) { // Getting the profile will fail on the CMYK palette as the profile property is private and as the class // has to be reflected this private property will be on the _Original class and not on the proxy class and // is as such not accessible for property_exists in ObjectAccess::getProperty // @see NEOS-423 return $this->createAndSetProfileOnProxy($proxy, $profilePath); } if (!$profile instanceof ProfileInterface) { $profile = $this->createAndSetProfileOnProxy($proxy, $profilePath); } return $profile; }
/** * Get a single property reduced to a simple type (no objects) representation * * @param NodeInterface $node * @param string $propertyName * @return mixed */ public function getProperty(NodeInterface $node, $propertyName) { if ($propertyName[0] === '_') { $propertyValue = ObjectAccess::getProperty($node, ltrim($propertyName, '_')); } else { $propertyValue = $node->getProperty($propertyName); } $dataType = $node->getNodeType()->getPropertyType($propertyName); try { $convertedValue = $this->convertValue($propertyValue, $dataType); } catch (PropertyException $exception) { $this->systemLogger->logException($exception); $convertedValue = null; } if ($convertedValue === null) { $convertedValue = $this->getDefaultValueForProperty($node->getNodeType(), $propertyName); } return $convertedValue; }
/** * Get a value of the context * * This basically acts as a safe access to non-existing properties, unified array and * property access (using getters) and access to the current value (empty path). * * If a property or key did not exist this method will return NULL. * * @param string|integer|Context $path The path as string or Context value, will be unwrapped for convenience * @return mixed The value * @throws EvaluationException */ public function get($path) { if ($path instanceof Context) { $path = $path->unwrap(); } if ($path === null) { return null; } elseif (is_string($path) || is_integer($path)) { if (is_array($this->value)) { return array_key_exists($path, $this->value) ? $this->value[$path] : null; } elseif (is_object($this->value)) { try { return ObjectAccess::getProperty($this->value, $path); } catch (PropertyNotAccessibleException $exception) { return null; } } } else { throw new EvaluationException('Path is not of type string or integer, got ' . gettype($path), 1344418464); } }
/** * @test */ public function ignoredPropertiesShouldNotBeUsedAsMatcher() { $path = 'page/body/content/main'; $ignoredProperties = array('nodePath'); $mockTsRuntime = $this->getMockBuilder(Runtime::class)->disableOriginalConstructor()->getMock(); $mockTsRuntime->expects($this->any())->method('evaluate')->will($this->returnCallback(function ($evaluatePath, $that) use($path, $ignoredProperties) { $relativePath = str_replace($path . '/', '', $evaluatePath); switch ($relativePath) { case '__meta/ignoreProperties': return $ignoredProperties; } return ObjectAccess::getProperty($that, $relativePath, true); })); $typoScriptObjectName = 'Neos.Neos:PrimaryContent'; $renderer = new CaseImplementation($mockTsRuntime, $path, $typoScriptObjectName); $renderer->setIgnoreProperties($ignoredProperties); $renderer['nodePath'] = 'main'; $renderer['default'] = array('condition' => 'true'); $mockTsRuntime->expects($this->once())->method('render')->with('page/body/content/main/default<Neos.Fusion:Matcher>')->will($this->returnValue('rendered matcher')); $result = $renderer->evaluate(); $this->assertEquals('rendered matcher', $result); }
/** * Get a variable by dotted path expression, retrieving the * variable from nested arrays/objects one segment at a time. * If the second argument is provided, it must be an array of * accessor names which can be used to extract each value in * the dotted path. * * @param string $path * @param array $accessors * @return mixed */ public function getByPath($path, array $accessors = []) { $propertyPathSegments = explode('.', $path); $subject = $this->variables; foreach ($propertyPathSegments as $propertyName) { if ($subject === null) { break; } try { $subject = ObjectAccess::getProperty($subject, $propertyName); } catch (PropertyNotAccessibleException $exception) { $subject = null; } if ($subject instanceof TemplateObjectAccessInterface) { $subject = $subject->objectAccess(); } } if ($subject === null) { $subject = $this->getBooleanValue($path); } return $subject; }
/** * Checks if the given value is a unique entity depending on it's identity properties or * custom configured identity properties. * * @param mixed $value The value that should be validated * @return void * @throws InvalidValidationOptionsException * @api */ protected function isValid($value) { if (!is_object($value)) { throw new InvalidValidationOptionsException('The value supplied for the UniqueEntityValidator must be an object.', 1358454270); } $classSchema = $this->reflectionService->getClassSchema(TypeHandling::getTypeForValue($value)); if ($classSchema === null || $classSchema->getModelType() !== ClassSchema::MODELTYPE_ENTITY) { throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must be an entity.', 1358454284); } if ($this->options['identityProperties'] !== null) { $identityProperties = $this->options['identityProperties']; foreach ($identityProperties as $propertyName) { if ($classSchema->hasProperty($propertyName) === false) { throw new InvalidValidationOptionsException(sprintf('The custom identity property name "%s" supplied for the UniqueEntityValidator does not exists in "%s".', $propertyName, $classSchema->getClassName()), 1358960500); } } } else { $identityProperties = array_keys($classSchema->getIdentityProperties()); } if (count($identityProperties) === 0) { throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must have at least one identity property.', 1358459831); } $identifierProperties = $this->reflectionService->getPropertyNamesByAnnotation($classSchema->getClassName(), 'Doctrine\\ORM\\Mapping\\Id'); if (count($identifierProperties) > 1) { throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must only have one identifier property @ORM\\Id.', 1358501745); } $identifierPropertyName = count($identifierProperties) > 0 ? array_shift($identifierProperties) : 'Persistence_Object_Identifier'; $query = $this->persistenceManager->createQueryForType($classSchema->getClassName()); $constraints = [$query->logicalNot($query->equals($identifierPropertyName, $this->persistenceManager->getIdentifierByObject($value)))]; foreach ($identityProperties as $propertyName) { $constraints[] = $query->equals($propertyName, ObjectAccess::getProperty($value, $propertyName)); } if ($query->matching($query->logicalAnd($constraints))->count() > 0) { $this->addError('Another entity with the same unique identifiers already exists', 1355785874); } }
/** * 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 ObjectAccess::getProperty($object, $idPropertyName, true); } elseif (property_exists($object, 'Persistence_Object_Identifier')) { return ObjectAccess::getProperty($object, 'Persistence_Object_Identifier', true); } return null; }
/** * 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 (property_exists($object, 'Persistence_Object_Identifier')) { $identifierCandidate = ObjectAccess::getProperty($object, 'Persistence_Object_Identifier', true); if ($identifierCandidate !== null) { return $identifierCandidate; } } if ($this->entityManager->contains($object)) { try { return current($this->entityManager->getUnitOfWork()->getEntityIdentifier($object)); } catch (\Doctrine\ORM\ORMException $exception) { } } return null; }
/** * Returns the specified property. * * If the node has a content object attached, the property will be fetched * there if it is gettable. * * @param string $propertyName Name of the property * @return mixed value of the property * @throws NodeException if the content object exists but does not contain the specified property. */ public function getProperty($propertyName) { if (!is_object($this->contentObjectProxy)) { $value = isset($this->properties[$propertyName]) ? $this->properties[$propertyName] : null; if (!empty($value)) { if ($this->getNodeType()->getPropertyType($propertyName) === 'references') { if (!is_array($value)) { $value = array(); } } } return $value; } elseif (ObjectAccess::isPropertyGettable($this->contentObjectProxy->getObject(), $propertyName)) { return ObjectAccess::getProperty($this->contentObjectProxy->getObject(), $propertyName); } throw new NodeException(sprintf('Property "%s" does not exist in content object of type %s.', $propertyName, get_class($this->contentObjectProxy->getObject())), 1291286995); }
/** * @test * @expectedException \Neos\Utility\Exception\PropertyNotAccessibleException */ public function accessorCacheIsNotUsedForStdClass() { $object1 = new \stdClass(); $object1->property = 'booh!'; $object2 = new \stdClass(); $this->assertEquals('booh!', ObjectAccess::getProperty($object1, 'property')); ObjectAccess::getProperty($object2, 'property'); }
/** * Serialize entities that are inside an array or SplObjectStorage * * @param string $path * @param mixed $propertyValue * @param string $originalPropertyName * @return void */ private function Flow_searchForEntitiesAndStoreIdentifierArray($path, $propertyValue, $originalPropertyName) { if (is_array($propertyValue) || is_object($propertyValue) && ($propertyValue instanceof \ArrayObject || $propertyValue instanceof \SplObjectStorage)) { foreach ($propertyValue as $key => $value) { $this->Flow_searchForEntitiesAndStoreIdentifierArray($path . '.' . $key, $value, $originalPropertyName); } } elseif ($propertyValue instanceof PersistenceMagicInterface && !Bootstrap::$staticObjectManager->get(PersistenceManagerInterface::class)->isNewObject($propertyValue) || $propertyValue instanceof OrmProxy) { if (!property_exists($this, 'Flow_Persistence_RelatedEntities') || !is_array($this->Flow_Persistence_RelatedEntities)) { $this->Flow_Persistence_RelatedEntities = []; $this->Flow_Object_PropertiesToSerialize[] = 'Flow_Persistence_RelatedEntities'; } if ($propertyValue instanceof OrmProxy) { $className = get_parent_class($propertyValue); } else { $className = Bootstrap::$staticObjectManager->getObjectNameByClassName(get_class($propertyValue)); } $identifier = Bootstrap::$staticObjectManager->get(PersistenceManagerInterface::class)->getIdentifierByObject($propertyValue); if (!$identifier && $propertyValue instanceof OrmProxy) { $identifier = current(ObjectAccess::getProperty($propertyValue, '_identifier', true)); } $this->Flow_Persistence_RelatedEntities[$originalPropertyName . '.' . $path] = ['propertyName' => $originalPropertyName, 'entityType' => $className, 'identifier' => $identifier, 'entityPath' => $path]; $this->{$originalPropertyName} = Arrays::setValueByPath($this->{$originalPropertyName}, $path, null); } }
/** * Traverses the given object structure in order to transform it into an * array structure. * * @param object $object Object to traverse * @param array $configuration Configuration for transforming the given object or NULL * @return array Object structure as an array */ protected function transformObject($object, array $configuration) { if ($object instanceof \DateTimeInterface) { return $object->format(\DateTime::ISO8601); } else { $propertyNames = ObjectAccess::getGettablePropertyNames($object); $propertiesToRender = []; 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 = 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); } if (isset($configuration['_exposeClassName']) && ($configuration['_exposeClassName'] === self::EXPOSE_CLASSNAME_FULLY_QUALIFIED || $configuration['_exposeClassName'] === self::EXPOSE_CLASSNAME_UNQUALIFIED)) { $className = TypeHandling::getTypeForValue($object); $classNameParts = explode('\\', $className); $propertiesToRender['__class'] = $configuration['_exposeClassName'] === self::EXPOSE_CLASSNAME_FULLY_QUALIFIED ? $className : array_pop($classNameParts); } return $propertiesToRender; } }
/** * @test */ public function validationIsStoppedAtAggregateBoundaries() { $relatedEntity = new TestEntity(); $relatedEntity->setName('Spy'); $this->testEntityRepository->add($relatedEntity); $entity = new TestEntity(); $entity->setName('Some Name'); $entity->setRelatedEntity($relatedEntity); $this->testEntityRepository->add($entity); $this->persistenceManager->persistAll(); $entityIdentifier = $this->persistenceManager->getIdentifierByObject($relatedEntity); /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ $entityManager = ObjectAccess::getProperty($this->persistenceManager, 'entityManager', true); $dql = 'UPDATE ' . TestEntity::class . " e SET e.name = 'xx' WHERE e.Persistence_Object_Identifier = '{$entityIdentifier}'"; $query = $entityManager->createQuery($dql); $query->getScalarResult(); $this->persistenceManager->clearState(); $entityIdentifier = $this->persistenceManager->getIdentifierByObject($entity); $invalidArguments = array('entity' => array('__identity' => $entityIdentifier, 'name' => 'Some other Name')); $response = $this->browser->request('http://localhost/test/validation/entity/update', 'POST', $invalidArguments); $this->assertNotSame('An error occurred while trying to call Neos\\Flow\\Tests\\Functional\\Mvc\\Fixtures\\Controller\\EntityController->updateAction().' . PHP_EOL . 'Error for entity.relatedEntity.name: This field must contain at least 3 characters.' . PHP_EOL, $response->getContent()); $this->assertSame(200, $response->getStatusCode()); }
/** * After returning advice, generates the value hash for the object * * @param JoinPointInterface $joinPoint The current join point * @return void * @Flow\After("Neos\Flow\Persistence\Aspect\PersistenceMagicAspect->isNonEmbeddedValueObject && method(.*->__construct()) && filter(Neos\Flow\Persistence\Doctrine\Mapping\Driver\FlowAnnotationDriver)") */ public function generateValueHash(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $proxyClassName = get_class($proxy); $hashSourceParts = []; $classSchema = $this->reflectionService->getClassSchema($proxyClassName); foreach ($classSchema->getProperties() as $property => $propertySchema) { // Currently, private properties are transient. Should this behaviour change, they need to be included // in the value hash generation if ($classSchema->isPropertyTransient($property) || $this->reflectionService->isPropertyPrivate($proxyClassName, $property)) { continue; } $propertyValue = ObjectAccess::getProperty($proxy, $property, true); if (is_object($propertyValue) === true) { // The persistence manager will return NULL if the given object is unknown to persistence $propertyValue = $this->persistenceManager->getIdentifierByObject($propertyValue) ?: $propertyValue; } $hashSourceParts[$property] = $propertyValue; } ksort($hashSourceParts); $hashSourceParts['__class_name__'] = $proxyClassName; $serializedSource = $this->useIgBinary === true ? igbinary_serialize($hashSourceParts) : serialize($hashSourceParts); $proxy = $joinPoint->getProxy(); ObjectAccess::setProperty($proxy, 'Persistence_Object_Identifier', sha1($serializedSource), true); }
/** * @test */ public function parseDesignatorMethodAnnotatedWithObservesAnnotationPropertyConstraints() { $this->mockObjectManager->expects($this->any())->method('get')->will($this->returnValue($this->createMock(SystemLoggerInterface::class))); $pointcutFilterComposite = new PointcutFilterComposite(); $parser = $this->getAccessibleMock(PointcutExpressionParser::class, ['dummy'], [], '', false); $parser->injectReflectionService($this->mockReflectionService); $parser->injectObjectManager($this->mockObjectManager); $parser->_call('parseDesignatorMethodAnnotatedWith', '&&', 'foo(bar == FALSE)', $pointcutFilterComposite); $expectedAnnotation = 'foo'; $expectedAnnotationValueConstraints = ['bar' => ['operator' => [0 => '=='], 'value' => [0 => 'FALSE']]]; $filters = ObjectAccess::getProperty($pointcutFilterComposite, 'filters', true); $filter = $filters[0][1]; $annotation = ObjectAccess::getProperty($filter, 'annotation', true); $annotationValueConstraints = ObjectAccess::getProperty($filter, 'annotationValueConstraints', true); $this->assertEquals($expectedAnnotation, $annotation); $this->assertEquals($expectedAnnotationValueConstraints, $annotationValueConstraints); }
/** * Registers an object which has been created or cloned during this request. * * The given object must contain the Persistence_Object_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 Aspect\PersistenceMagicInterface $object The new object to register * @return void */ public function registerNewObject(Aspect\PersistenceMagicInterface $object) { $identifier = ObjectAccess::getProperty($object, 'Persistence_Object_Identifier', true); $this->newObjects[$identifier] = $object; }
/** * 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) { $object->__load(); } if (ObjectAccess::isPropertyGettable($object, $propertyName)) { return ObjectAccess::getProperty($object, $propertyName); } else { return ObjectAccess::getProperty($object, $propertyName, true); } }
/** * Convert an object from $source to an entity or a value object. * * @param mixed $source * @param string $targetType * @param array $convertedChildProperties * @param PropertyMappingConfigurationInterface $configuration * @return object|TargetNotFoundError the converted entity/value object or an instance of TargetNotFoundError if the object could not be resolved * @throws \InvalidArgumentException|InvalidTargetException */ public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null) { if (is_array($source)) { if ($this->reflectionService->isClassAnnotatedWith($targetType, ValueObject::class)) { if (isset($source['__identity']) && count($source) > 1) { // @TODO fix that in the URI building and transfer VOs as values instead as with their identities // Unset identity for value objects to use constructor mapping, since the identity is determined from // property values after construction unset($source['__identity']); } } $object = $this->handleArrayData($source, $targetType, $convertedChildProperties, $configuration); if ($object instanceof TargetNotFoundError) { return $object; } } elseif (is_string($source)) { if ($source === '') { return null; } $object = $this->fetchObjectFromPersistence($source, $targetType); if ($object === null) { return new TargetNotFoundError(sprintf('Object of type "%s" with identity "%s" not found.', $targetType, $source), 1412283033); } } else { throw new \InvalidArgumentException('Only strings and arrays are accepted.', 1305630314); } $objectConstructorArguments = $this->getConstructorArgumentsForClass(TypeHandling::getTypeForValue($object)); foreach ($convertedChildProperties as $propertyName => $propertyValue) { // We need to check for "immutable" constructor arguments that have no setter and remove them. if (isset($objectConstructorArguments[$propertyName]) && !ObjectAccess::isPropertySettable($object, $propertyName)) { $currentPropertyValue = ObjectAccess::getProperty($object, $propertyName); if ($currentPropertyValue === $propertyValue) { continue; } else { $exceptionMessage = sprintf('Property "%s" having a value of type "%s" could not be set in target object of type "%s". The property has no setter and is not equal to the value in the object, in that case it would have been skipped.', $propertyName, is_object($propertyValue) ? TypeHandling::getTypeForValue($propertyValue) : gettype($propertyValue), $targetType); throw new InvalidTargetException($exceptionMessage, 1421498771); } } $result = ObjectAccess::setProperty($object, $propertyName, $propertyValue); if ($result === false) { $exceptionMessage = sprintf('Property "%s" having a value of type "%s" could not be set in target object of type "%s". Make sure that the property is accessible properly, for example via an appropriate setter method.', $propertyName, is_object($propertyValue) ? TypeHandling::getTypeForValue($propertyValue) : gettype($propertyValue), $targetType); throw new InvalidTargetException($exceptionMessage, 1297935345); } } return $object; }
/** * Compare a request propertyValue against an expected * value and add the weight if it's TRUE * * @param string $propertyName * @param string $expectedValue * @param integer $weight * @return boolean */ protected function matchRequestProperty($propertyName, $expectedValue, $weight) { if ($this->request === null) { return false; } $value = ObjectAccess::getProperty($this->request, $propertyName); if ($value === $expectedValue) { $this->addWeight($weight); return true; } return false; }
/** * Make the node "similar" to the given source node. That means, * - all properties * - index * - node type * - content object * will be set to the same values as in the source node. * * @param AbstractNodeData $sourceNode * @param boolean $isCopy * @return void */ public function similarize(AbstractNodeData $sourceNode, $isCopy = false) { $this->properties = []; foreach ($sourceNode->getProperties() as $propertyName => $propertyValue) { $this->setProperty($propertyName, $propertyValue); } $propertyNames = ['nodeType', 'hidden', 'hiddenAfterDateTime', 'hiddenBeforeDateTime', 'hiddenInIndex', 'accessRoles']; if (!$isCopy) { $propertyNames[] = 'creationDateTime'; $propertyNames[] = 'lastModificationDateTime'; } if ($sourceNode instanceof NodeData) { $propertyNames[] = 'index'; } foreach ($propertyNames as $propertyName) { ObjectAccess::setProperty($this, $propertyName, ObjectAccess::getProperty($sourceNode, $propertyName)); } $contentObject = $sourceNode->getContentObject(); if ($contentObject !== null) { $this->setContentObject($contentObject); } }
/** * 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 UnexpectedTypeException * @throws PersistenceException * @throws IllegalObjectTypeException * @api */ protected function checkPropertyValue($object, $propertyName, array $propertyMetaData) { $propertyValue = ObjectAccess::getProperty($object, $propertyName, true); $propertyType = $propertyMetaData['type']; if ($propertyType === 'ArrayObject') { throw new PersistenceException('ArrayObject properties are not supported - missing feature?!?', 1283524355); } if (is_object($propertyValue)) { if ($propertyType === 'object') { if (!$propertyValue instanceof PersistenceMagicInterface) { throw new 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 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 UnexpectedTypeException('Expected property of type ' . $propertyType . ', but got ' . gettype($propertyValue) . ' for ' . get_class($object) . '::' . $propertyName, 1244465559); } return $propertyValue; }
/** * 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 || $object instanceof \ArrayObject) { return self::renderArrayDump(\Doctrine\Common\Util\Debug::export($object, 3), $level, $plaintext, $ansiColors); } // Objects returned from Doctrine's Debug::export function are stdClass with special properties: try { $objectIdentifier = ObjectAccess::getProperty($object, 'Persistence_Object_Identifier', true); } catch (\Neos\Utility\Exception\PropertyNotAccessibleException $exception) { $objectIdentifier = spl_object_hash($object); } $className = $object instanceof \stdClass && isset($object->__CLASS__) ? $object->__CLASS__ : get_class($object); if (isset(self::$renderedObjects[$objectIdentifier]) || preg_match(self::getIgnoredClassesRegex(), $className) !== 0) { $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 Configuration::SCOPE_PROTOTYPE: $scope = 'prototype'; break; case Configuration::SCOPE_SINGLETON: $scope = 'singleton'; break; case 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, 'Persistence_Object_Identifier')) { $persistenceIdentifier = $objectIdentifier; $persistenceType = 'persistable'; } elseif ($object instanceof \Closure) { $persistenceIdentifier = 'n/a'; $persistenceType = 'closure'; } 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 ProxyInterface || property_exists($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 { $objectReflection = new \ReflectionObject($object); $properties = $objectReflection->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; }