/**
  * 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();
 }