/** * Evaluate this node and return the correct object. * * Handles each part (denoted by .) in $this->objectPath in the following order: * - call appropriate getter * - call public property, if exists * - fail * * The first part of the object path has to be a variable in the * TemplateVariableContainer. * * @return object The evaluated object, can be any object type. * @author Sebastian Kurfürst <*****@*****.**> * @author Bastian Waidelich <*****@*****.**> * @todo Depending on the context, either fail or not!!! */ public function evaluate() { $objectPathParts = explode('.', $this->objectPath); $variableName = array_shift($objectPathParts); if (!$this->renderingContext->getTemplateVariableContainer()->exists($variableName)) { return NULL; } $currentObject = $this->renderingContext->getTemplateVariableContainer()->get($variableName); if (count($objectPathParts) > 0) { return \F3\FLOW3\Reflection\ObjectAccess::getPropertyPath($currentObject, implode('.', $objectPathParts)); } else { return $currentObject; } }
/** * Get the current property of the object bound to this form. * * @return mixed Value * @author Bastian Waidelich <*****@*****.**> */ protected function getPropertyValue() { $formObject = $this->viewHelperVariableContainer->get('F3\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject'); $propertyName = $this->arguments['property']; if (is_array($formObject)) { return isset($formObject[$propertyName]) ? $formObject[$propertyName] : NULL; } return \F3\FLOW3\Reflection\ObjectAccess::getPropertyPath($formObject, $propertyName); }
/** * Loop through all gettable properties of the $newObject and call update() * on them if they are entities/valueobjects. * This makes sure that changes to subobjects of a given object are * persisted as well. * * @param object $newObject The new object to loop over * @author Sebastian Kurfürst <*****@*****.**> */ protected function updateRecursively($newObject) { $propertiesOfNewObject = \F3\FLOW3\Reflection\ObjectAccess::getGettableProperties($newObject); foreach ($propertiesOfNewObject as $subObject) { if ($subObject instanceof \F3\FLOW3\Persistence\Aspect\DirtyMonitoringInterface && $subObject->FLOW3_Persistence_isClone()) { $this->updateObject($subObject); $this->updateRecursively($subObject); } } }
/** * Iterates through elements of $each and renders child nodes * * @param array $each The array or \SplObjectStorage to iterated over * @param string $as The name of the iteration variable * @param string $groupBy Group by this property * @param string $groupKey The name of the variable to store the current group * @return string Rendered string * @author Bastian Waidelich <*****@*****.**> * @api */ public function render($each, $as, $groupBy, $groupKey = 'groupKey') { $output = ''; if ($each === NULL) { return ''; } if (is_object($each)) { if (!$each instanceof \Traversable) { throw new \F3\Fluid\Core\ViewHelper\Exception('GroupedForViewHelper only supports arrays and objects implementing \\Traversable interface', 1253108907); } $each = $this->convertToArray($each); } $groups = array(); foreach ($each as $keyValue => $singleElement) { if (is_array($singleElement)) { $currentGroupKey = isset($singleElement[$groupBy]) ? $singleElement[$groupBy] : NULL; } elseif (is_object($singleElement)) { $currentGroupKey = \F3\FLOW3\Reflection\ObjectAccess::getProperty($singleElement, $groupBy); } else { throw new \F3\Fluid\Core\ViewHelper\Exception('GroupedForViewHelper only supports multi-dimensional arrays and objects', 1253120365); } $groups[$currentGroupKey][$keyValue] = $singleElement; } foreach ($groups as $currentGroupKey => $group) { $this->templateVariableContainer->add($groupKey, $currentGroupKey); $this->templateVariableContainer->add($as, $group); $output .= $this->renderChildren(); $this->templateVariableContainer->remove($groupKey); $this->templateVariableContainer->remove($as); } return $output; }
/** * Checks if the specified property of the given object is valid. * * If at least one error occurred, the result is FALSE. * * @param object $object The object containing the property to validate * @param string $propertyName Name of the property to validate * @return boolean TRUE if the property value is valid, FALSE if an error occured * @author Robert Lemke <*****@*****.**> * @api */ public function isPropertyValid($object, $propertyName) { if (!is_object($object)) { throw new \InvalidArgumentException('Object expected, ' . gettype($object) . ' given.', 1241099149); } if (!isset($this->propertyValidators[$propertyName])) { return TRUE; } $result = TRUE; foreach ($this->propertyValidators[$propertyName] as $validator) { if (\F3\FLOW3\Reflection\ObjectAccess::isPropertyGettable($object, $propertyName)) { $propertyValue = \F3\FLOW3\Reflection\ObjectAccess::getProperty($object, $propertyName); } else { $propertyReflection = new \F3\FLOW3\Reflection\PropertyReflection(get_class($object), $propertyName); $propertyReflection->setAccessible(TRUE); $propertyValue = $propertyReflection->getValue($object); } if ($validator->isValid($propertyValue) === FALSE) { $this->addErrorsForProperty($validator->getErrors(), $propertyName); $result = FALSE; } } return $result; }
/** * @test * @author Karsten Dambekalns <*****@*****.**> */ public function getPropertyPathReturnsNullForNonExistingPropertyPath() { $alternativeObject = new \F3\FLOW3\Tests\Reflection\Fixture\DummyClassWithGettersAndSetters(); $alternativeObject->setProperty(new \stdClass()); $this->dummyObject->setProperty2($alternativeObject); $this->assertNull(\F3\FLOW3\Reflection\ObjectAccess::getPropertyPath($this->dummyObject, 'property2.property.not.existing')); }
/** * Retrieves the selected value(s) * * @return mixed value string or an array of strings * @author Bastian Waidelich <*****@*****.**> */ protected function getSelectedValue() { $value = $this->getValue(); if (!$this->arguments->hasArgument('optionValueField')) { return $value; } if (!is_array($value) && !$value instanceof Iterator) { if (is_object($value)) { return \F3\FLOW3\Reflection\ObjectAccess::getProperty($value, $this->arguments['optionValueField']); } else { return $value; } } $selectedValues = array(); foreach ($value as $selectedValueElement) { if (is_object($selectedValueElement)) { $selectedValues[] = \F3\FLOW3\Reflection\ObjectAccess::getProperty($selectedValueElement, $this->arguments['optionValueField']); } else { $selectedValues[] = $selectedValueElement; } } return $selectedValues; }
/** * Maps the given properties to the target object WITHOUT VALIDATING THE RESULT. * If the properties could be set, this method returns TRUE, otherwise FALSE. * Returning TRUE does not mean that the target object is valid and secure! * * Only use this method if you're sure that you don't need validation! * * @param array $propertyNames Names of the properties to map. * @param mixed $source Source containing the properties to map to the target object. Must either be an array, ArrayObject or any other object. * @param object $target The target object * @param array $optionalPropertyNames Names of optional properties. If a property is specified here and it doesn't exist in the source, no error is issued. * @return boolean TRUE if the properties could be mapped, otherwise FALSE * @see mapAndValidate() * @author Robert Lemke <*****@*****.**> * @api */ public function map(array $propertyNames, $source, &$target, $optionalPropertyNames = array()) { if (!is_object($source) && !is_array($source)) { throw new \F3\FLOW3\Property\Exception\InvalidSourceException('The source object must be a valid object or array, ' . gettype($target) . ' given.', 1187807099); } if (is_string($target) && strpos($target, '\\') !== FALSE) { return $this->transformToObject($source, $target, '--none--'); } $this->mappingResults = $this->objectManager->getObject('F3\\FLOW3\\Property\\MappingResults'); if (!is_object($target) && !is_array($target)) { throw new \F3\FLOW3\Property\Exception\InvalidTargetException('The target must be a valid object, class name or array, ' . gettype($target) . ' given.', 1187807099); } if (is_object($target)) { $targetClassSchema = $this->reflectionService->getClassSchema($target); } else { $targetClassSchema = NULL; } foreach ($propertyNames as $propertyName) { $propertyValue = NULL; if (is_array($source) || $source instanceof \ArrayAccess) { if (isset($source[$propertyName])) { $propertyValue = $source[$propertyName]; } } elseif (\F3\FLOW3\Reflection\ObjectAccess::isPropertyGettable($source, $propertyName)) { $propertyValue = \F3\FLOW3\Reflection\ObjectAccess::getProperty($source, $propertyName); } if ($propertyValue === NULL && !in_array($propertyName, $optionalPropertyNames)) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Required property '{$propertyName}' does not exist in source.", 1236785359), $propertyName); } else { if (method_exists($target, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)) && is_callable(array($target, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)))) { $targetClassName = $target instanceof \F3\FLOW3\AOP\ProxyInterface ? $target->FLOW3_AOP_Proxy_getProxyTargetClassName() : get_class($target); $methodParameters = $this->reflectionService->getMethodParameters($targetClassName, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)); $methodParameter = current($methodParameters); $targetPropertyType = \F3\FLOW3\Utility\TypeHandling::parseType($methodParameter['type']); } elseif ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) { $targetPropertyType = $targetClassSchema->getProperty($propertyName); } elseif ($targetClassSchema !== NULL) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Property '{$propertyName}' does not exist in target class schema.", 1251813614), $propertyName); continue; } if (isset($targetPropertyType)) { if (in_array($targetPropertyType['type'], array('array', 'ArrayObject', 'SplObjectStorage')) && strpos($targetPropertyType['elementType'], '\\') !== FALSE) { $objects = array(); foreach ($propertyValue as $value) { $objects[] = $this->transformToObject($value, $targetPropertyType['elementType'], $propertyName); } if ($targetPropertyType['type'] === 'ArrayObject') { $propertyValue = new \ArrayObject($objects); } elseif ($targetPropertyType['type'] === 'SplObjectStorage') { $propertyValue = new \SplObjectStorage(); foreach ($objects as $object) { $propertyValue->attach($object); } } else { $propertyValue = $objects; } } elseif (strpos($targetPropertyType['type'], '\\') !== FALSE) { $propertyValue = $this->transformToObject($propertyValue, $targetPropertyType['type'], $propertyName); } } if (is_array($target)) { $target[$propertyName] = $propertyValue; } elseif (\F3\FLOW3\Reflection\ObjectAccess::setProperty($target, $propertyName, $propertyValue) === FALSE) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Property '{$propertyName}' could not be set.", 1236783102), $propertyName); } } } return !$this->mappingResults->hasErrors(); }