public function transform($value)
 {
     if (null !== $value && !is_scalar($value)) {
         throw new UnexpectedTypeException($value, 'scalar');
     }
     return FormUtil::toArrayKey($value);
 }
Exemple #2
0
 /**
  * finds the method used to append values to the named property
  *
  * @param mixed  $object
  * @param string $property
  */
 private function findAdderMethod($object, $property)
 {
     if (method_exists($object, $method = 'add' . $property)) {
         return $method;
     }
     if (class_exists('Symfony\\Component\\PropertyAccess\\StringUtil') && method_exists('Symfony\\Component\\PropertyAccess\\StringUtil', 'singularify')) {
         foreach ((array) StringUtil::singularify($property) as $singularForm) {
             if (method_exists($object, $method = 'add' . $singularForm)) {
                 return $method;
             }
         }
     } elseif (class_exists('Symfony\\Component\\Form\\Util\\FormUtil') && method_exists('Symfony\\Component\\Form\\Util\\FormUtil', 'singularify')) {
         foreach ((array) FormUtil::singularify($property) as $singularForm) {
             if (method_exists($object, $method = 'add' . $singularForm)) {
                 return $method;
             }
         }
     }
     if (method_exists($object, $method = 'add' . rtrim($property, 's'))) {
         return $method;
     }
     if (substr($property, -3) === 'ies' && method_exists($object, $method = 'add' . substr($key, 0, -3) . 'y')) {
         return $method;
     }
 }
 public function testToArrayKeys()
 {
     $in = $out = array();
     foreach ($this->toArrayKeyProvider() as $call) {
         $in[] = $call[0];
         $out[] = $call[1];
     }
     $this->assertSame($out, FormUtil::toArrayKeys($in));
 }
 /**
  * @param array $array
  *
  * @return array
  *
  * @throws UnexpectedTypeException if the given value is not an array
  */
 public function transform($array)
 {
     if (null === $array) {
         return array();
     }
     if (!is_array($array)) {
         throw new UnexpectedTypeException($array, 'array');
     }
     return FormUtil::toArrayKeys($array);
 }
 /**
  * Transforms a single choice to a format appropriate for the nested
  * checkboxes/radio buttons.
  *
  * The result is an array with the options as keys and true/false as values,
  * depending on whether a given option is selected. If this field is rendered
  * as select tag, the value is not modified.
  *
  * @param  mixed $value  An array if "multiple" is set to true, a scalar
  *                       value otherwise.
  *
  * @return mixed         An array
  *
  * @throws UnexpectedTypeException if the given value is not scalar
  * @throws TransformationFailedException if the choices can not be retrieved
  */
 public function transform($value)
 {
     if (!is_scalar($value) && null !== $value) {
         throw new UnexpectedTypeException($value, 'scalar');
     }
     try {
         $choices = $this->choiceList->getChoices();
     } catch (\Exception $e) {
         throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
     }
     $value = FormUtil::toArrayKey($value);
     foreach (array_keys($choices) as $key) {
         $choices[$key] = $key === $value;
     }
     return $choices;
 }
 public function noAdderRemoverData()
 {
     $data = array();
     $car = $this->getMock(__CLASS__ . '_CarNoAdderAndRemover');
     $propertyPath = new PropertyPath('axes');
     $expectedMessage = sprintf('Neither element "axes" nor method "setAxes()" exists in class ' . '"%s", nor could adders and removers be found based on the ' . 'guessed singulars: %s (provide a singular by suffixing the ' . 'property path with "|{singular}" to override the guesser)', get_class($car), implode(', ', (array) ($singulars = FormUtil::singularify('Axes'))));
     $data[] = array($car, $propertyPath, $expectedMessage);
     /*
             Temporarily disabled in 2.1
     
             $propertyPath = new PropertyPath('axes|boo');
             $expectedMessage = sprintf(
        'Neither element "axes" nor method "setAxes()" exists in class '
            .'"%s", nor could adders and removers be found based on the '
            .'passed singular: %s',
        get_class($car),
        'boo'
             );
             $data[] = array($car, $propertyPath, $expectedMessage);
     */
     $car = $this->getMock(__CLASS__ . '_CarNoAdderAndRemoverWithProperty');
     $propertyPath = new PropertyPath('axes');
     $expectedMessage = sprintf('Property "axes" is not public in class "%s", nor could adders and ' . 'removers be found based on the guessed singulars: %s ' . '(provide a singular by suffixing the property path with ' . '"|{singular}" to override the guesser). Maybe you should ' . 'create the method "setAxes()"?', get_class($car), implode(', ', (array) ($singulars = FormUtil::singularify('Axes'))));
     $data[] = array($car, $propertyPath, $expectedMessage);
     return $data;
 }
Exemple #7
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(FormBuilderInterface $builder, array $options)
 {
     $choiceList = $this->createChoiceList($options);
     $builder->setAttribute('choice_list', $choiceList);
     if ($options['expanded']) {
         $builder->setDataMapper($options['multiple'] ? new CheckboxListMapper() : new RadioListMapper());
         // Initialize all choices before doing the index check below.
         // This helps in cases where index checks are optimized for non
         // initialized choice lists. For example, when using an SQL driver,
         // the index check would read in one SQL query and the initialization
         // requires another SQL query. When the initialization is done first,
         // one SQL query is sufficient.
         $choiceListView = $this->createChoiceListView($choiceList, $options);
         $builder->setAttribute('choice_list_view', $choiceListView);
         // Check if the choices already contain the empty value
         // Only add the placeholder option if this is not the case
         if (null !== $options['placeholder'] && 0 === count($choiceList->getChoicesForValues(array('')))) {
             $placeholderView = new ChoiceView(null, '', $options['placeholder']);
             // "placeholder" is a reserved name
             $this->addSubForm($builder, 'placeholder', $placeholderView, $options);
         }
         $this->addSubForms($builder, $choiceListView->preferredChoices, $options);
         $this->addSubForms($builder, $choiceListView->choices, $options);
         // Make sure that scalar, submitted values are converted to arrays
         // which can be submitted to the checkboxes/radio buttons
         $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
             $form = $event->getForm();
             $data = $event->getData();
             if (null === $data) {
                 $emptyData = $form->getConfig()->getEmptyData();
                 if (false === FormUtil::isEmpty($emptyData) && array() !== $emptyData) {
                     $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData;
                 }
             }
             // Convert the submitted data to a string, if scalar, before
             // casting it to an array
             if (!is_array($data)) {
                 $data = (array) (string) $data;
             }
             // A map from submitted values to integers
             $valueMap = array_flip($data);
             // Make a copy of the value map to determine whether any unknown
             // values were submitted
             $unknownValues = $valueMap;
             // Reconstruct the data as mapping from child names to values
             $data = array();
             foreach ($form as $child) {
                 $value = $child->getConfig()->getOption('value');
                 // Add the value to $data with the child's name as key
                 if (isset($valueMap[$value])) {
                     $data[$child->getName()] = $value;
                     unset($unknownValues[$value]);
                     continue;
                 }
             }
             // The empty value is always known, independent of whether a
             // field exists for it or not
             unset($unknownValues['']);
             // Throw exception if unknown values were submitted
             if (count($unknownValues) > 0) {
                 throw new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues))));
             }
             $event->setData($data);
         });
     }
     if ($options['multiple']) {
         // <select> tag with "multiple" option or list of checkbox inputs
         $builder->addViewTransformer(new ChoicesToValuesTransformer($choiceList));
     } else {
         // <select> tag without "multiple" option or list of radio inputs
         $builder->addViewTransformer(new ChoiceToValueTransformer($choiceList));
     }
     if ($options['multiple'] && $options['by_reference']) {
         // Make sure the collection created during the client->norm
         // transformation is merged back into the original collection
         $builder->addEventSubscriber(new MergeCollectionListener(true, true));
     }
 }
Exemple #8
0
 /**
  * Sets the value of the property at the given index in the path
  *
  * @param object  $objectOrArray The object or array to traverse
  * @param integer $currentIndex  The index of the modified property in the path
  * @param mixed $value           The value to set
  */
 protected function writeProperty(&$objectOrArray, $currentIndex, $value)
 {
     $property = $this->elements[$currentIndex];
     if (is_object($objectOrArray) && $this->isIndex[$currentIndex]) {
         if (!$objectOrArray instanceof \ArrayAccess) {
             throw new InvalidPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \\ArrayAccess', $property, get_class($objectOrArray)));
         }
         $objectOrArray[$property] = $value;
     } elseif (is_object($objectOrArray)) {
         $reflClass = new ReflectionClass($objectOrArray);
         $setter = 'set' . $this->camelize($property);
         $addMethod = null;
         $removeMethod = null;
         $plural = null;
         // Check if the parent has matching methods to add/remove items
         if (is_array($value) || $value instanceof Traversable) {
             $singular = $this->singulars[$currentIndex];
             if (null !== $singular) {
                 $addMethod = 'add' . ucfirst($singular);
                 $removeMethod = 'remove' . ucfirst($singular);
                 if (!$this->isAccessible($reflClass, $addMethod, 1)) {
                     throw new InvalidPropertyException(sprintf('The public method "%s" with exactly one required parameter was not found on class %s', $addMethod, $reflClass->getName()));
                 }
                 if (!$this->isAccessible($reflClass, $removeMethod, 1)) {
                     throw new InvalidPropertyException(sprintf('The public method "%s" with exactly one required parameter was not found on class %s', $removeMethod, $reflClass->getName()));
                 }
             } else {
                 // The plural form is the last element of the property path
                 $plural = ucfirst($this->elements[$this->length - 1]);
                 // Any of the two methods is required, but not yet known
                 $singulars = (array) FormUtil::singularify($plural);
                 foreach ($singulars as $singular) {
                     $addMethodName = 'add' . $singular;
                     $removeMethodName = 'remove' . $singular;
                     if ($this->isAccessible($reflClass, $addMethodName, 1)) {
                         $addMethod = $addMethodName;
                     }
                     if ($this->isAccessible($reflClass, $removeMethodName, 1)) {
                         $removeMethod = $removeMethodName;
                     }
                     if ($addMethod && !$removeMethod) {
                         throw new InvalidPropertyException(sprintf('Found the public method "%s", but did not find a public "%s" on class %s', $addMethodName, $removeMethodName, $reflClass->getName()));
                     }
                     if ($removeMethod && !$addMethod) {
                         throw new InvalidPropertyException(sprintf('Found the public method "%s", but did not find a public "%s" on class %s', $removeMethodName, $addMethodName, $reflClass->getName()));
                     }
                     if ($addMethod && $removeMethod) {
                         break;
                     }
                 }
             }
         }
         // Collection with matching adder/remover in $objectOrArray
         if ($addMethod && $removeMethod) {
             $itemsToAdd = is_object($value) ? clone $value : $value;
             $itemToRemove = array();
             $previousValue = $this->readProperty($objectOrArray, $currentIndex);
             if (is_array($previousValue) || $previousValue instanceof Traversable) {
                 foreach ($previousValue as $previousItem) {
                     foreach ($value as $key => $item) {
                         if ($item === $previousItem) {
                             // Item found, don't add
                             unset($itemsToAdd[$key]);
                             // Next $previousItem
                             continue 2;
                         }
                     }
                     // Item not found, add to remove list
                     $itemToRemove[] = $previousItem;
                 }
             }
             foreach ($itemToRemove as $item) {
                 $objectOrArray->{$removeMethod}($item);
             }
             foreach ($itemsToAdd as $item) {
                 $objectOrArray->{$addMethod}($item);
             }
         } elseif ($reflClass->hasMethod($setter)) {
             if (!$reflClass->getMethod($setter)->isPublic()) {
                 throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
             }
             $objectOrArray->{$setter}($value);
         } elseif ($reflClass->hasMethod('__set')) {
             // needed to support magic method __set
             $objectOrArray->{$property} = $value;
         } elseif ($reflClass->hasProperty($property)) {
             if (!$reflClass->getProperty($property)->isPublic()) {
                 throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "%s()"?', $property, $reflClass->getName(), $setter));
             }
             $objectOrArray->{$property} = $value;
         } elseif (property_exists($objectOrArray, $property)) {
             // needed to support \stdClass instances
             $objectOrArray->{$property} = $value;
         } else {
             throw new InvalidPropertyException(sprintf('Neither element "%s" nor method "%s()" exists in class "%s"', $property, $setter, $reflClass->getName()));
         }
     } else {
         $objectOrArray[$property] = $value;
     }
 }
Exemple #9
0
 /**
  * @dataProvider isChoiceSelectedProvider
  */
 public function testIsChoiceSelected($expected, $choice, $value)
 {
     $this->assertSame($expected, FormUtil::isChoiceSelected($choice, $value));
 }
Exemple #10
0
 /**
  * Sets the value of the property at the given index in the path
  *
  * @param object|array $objectOrArray The object or array to write to.
  * @param string       $property      The property to write.
  * @param string|null  $singular      The singular form of the property name or null.
  * @param Boolean      $isIndex       Whether to interpret the property as index.
  * @param mixed        $value         The value to write.
  *
  * @throws InvalidPropertyException      If the property does not exist.
  * @throws PropertyAccessDeniedException If the property cannot be accessed due to
  *                                       access restrictions (private or protected).
  */
 private function writeProperty(&$objectOrArray, $property, $singular, $isIndex, $value)
 {
     $adderRemoverError = null;
     if ($isIndex) {
         if (!$objectOrArray instanceof \ArrayAccess && !is_array($objectOrArray)) {
             throw new InvalidPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \\ArrayAccess', $property, get_class($objectOrArray)));
         }
         $objectOrArray[$property] = $value;
     } elseif (is_object($objectOrArray)) {
         $reflClass = new ReflectionClass($objectOrArray);
         // The plural form is the last element of the property path
         $plural = $this->camelize($this->elements[$this->length - 1]);
         // Any of the two methods is required, but not yet known
         $singulars = null !== $singular ? array($singular) : (array) FormUtil::singularify($plural);
         if (is_array($value) || $value instanceof Traversable) {
             $methods = $this->findAdderAndRemover($reflClass, $singulars);
             if (null !== $methods) {
                 // At this point the add and remove methods have been found
                 // Use iterator_to_array() instead of clone in order to prevent side effects
                 // see https://github.com/symfony/symfony/issues/4670
                 $itemsToAdd = is_object($value) ? iterator_to_array($value) : $value;
                 $itemToRemove = array();
                 $propertyValue = $this->readProperty($objectOrArray, $property, $isIndex);
                 $previousValue = $propertyValue[self::VALUE];
                 if (is_array($previousValue) || $previousValue instanceof Traversable) {
                     foreach ($previousValue as $previousItem) {
                         foreach ($value as $key => $item) {
                             if ($item === $previousItem) {
                                 // Item found, don't add
                                 unset($itemsToAdd[$key]);
                                 // Next $previousItem
                                 continue 2;
                             }
                         }
                         // Item not found, add to remove list
                         $itemToRemove[] = $previousItem;
                     }
                 }
                 foreach ($itemToRemove as $item) {
                     call_user_func(array($objectOrArray, $methods[1]), $item);
                 }
                 foreach ($itemsToAdd as $item) {
                     call_user_func(array($objectOrArray, $methods[0]), $item);
                 }
                 return;
             } else {
                 $adderRemoverError = ', nor could adders and removers be found based on the ';
                 if (null === $singular) {
                     // $adderRemoverError .= 'guessed singulars: '.implode(', ', $singulars).' (provide a singular by suffixing the property path with "|{singular}" to override the guesser)';
                     $adderRemoverError .= 'guessed singulars: ' . implode(', ', $singulars);
                 } else {
                     $adderRemoverError .= 'passed singular: ' . $singular;
                 }
             }
         }
         $setter = 'set' . $this->camelize($property);
         if ($reflClass->hasMethod($setter)) {
             if (!$reflClass->getMethod($setter)->isPublic()) {
                 throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->name));
             }
             $objectOrArray->{$setter}($value);
         } elseif ($reflClass->hasMethod('__set')) {
             // needed to support magic method __set
             $objectOrArray->{$property} = $value;
         } elseif ($reflClass->hasProperty($property)) {
             if (!$reflClass->getProperty($property)->isPublic()) {
                 throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s"%s. Maybe you should create the method "%s()"?', $property, $reflClass->name, $adderRemoverError, $setter));
             }
             $objectOrArray->{$property} = $value;
         } elseif (property_exists($objectOrArray, $property)) {
             // needed to support \stdClass instances
             $objectOrArray->{$property} = $value;
         } else {
             throw new InvalidPropertyException(sprintf('Neither element "%s" nor method "%s()" exists in class "%s"%s', $property, $setter, $reflClass->name, $adderRemoverError));
         }
     } else {
         throw new InvalidPropertyException(sprintf('Cannot write property "%s" in an array. Maybe you should write the property path as "[%s]" instead?', $property, $property));
     }
 }
Exemple #11
0
 public function isChoiceSelected(FormView $view, ChoiceView $choice)
 {
     return FormUtil::isChoiceSelected($choice->getValue(), $view->get('value'));
 }
Exemple #12
0
 /**
  * {@inheritdoc}
  */
 public function isEmpty()
 {
     foreach ($this->children as $child) {
         if (!$child->isEmpty()) {
             return false;
         }
     }
     return FormUtil::isEmpty($this->modelData) || array() === $this->modelData;
 }
 public function transform($value)
 {
     return FormUtil::toArrayKey($value);
 }
 /**
  * @dataProvider singularifyProvider
  */
 public function testSingularify($plural, $singular)
 {
     $this->assertEquals($singular, FormUtil::singularify($plural));
 }
Exemple #15
0
 /**
  * Searches for add and remove methods.
  *
  * @param \ReflectionClass $reflClass The reflection class for the given object
  * @param string|null      $singular  The singular form of the property name or null.
  *
  * @return array|null An array containin the adder and remover when found, null otherwise.
  *
  * @throws InvalidPropertyException      If the property does not exist.
  */
 private function findAdderAndRemover(\ReflectionClass $reflClass, $singular)
 {
     if (null !== $singular) {
         $addMethod = 'add' . $this->camelize($singular);
         $removeMethod = 'remove' . $this->camelize($singular);
         if (!$this->isAccessible($reflClass, $addMethod, 1)) {
             throw new InvalidPropertyException(sprintf('The public method "%s" with exactly one required parameter was not found on class %s', $addMethod, $reflClass->name));
         }
         if (!$this->isAccessible($reflClass, $removeMethod, 1)) {
             throw new InvalidPropertyException(sprintf('The public method "%s" with exactly one required parameter was not found on class %s', $removeMethod, $reflClass->name));
         }
         return array($addMethod, $removeMethod);
     }
     // The plural form is the last element of the property path
     $plural = $this->camelize($this->elements[$this->length - 1]);
     // Any of the two methods is required, but not yet known
     $singulars = (array) FormUtil::singularify($plural);
     foreach ($singulars as $singular) {
         $addMethod = 'add' . $singular;
         $removeMethod = 'remove' . $singular;
         $addMethodFound = $this->isAccessible($reflClass, $addMethod, 1);
         $removeMethodFound = $this->isAccessible($reflClass, $removeMethod, 1);
         if ($addMethodFound && $removeMethodFound) {
             return array($addMethod, $removeMethod);
         }
         if ($addMethodFound xor $removeMethodFound) {
             throw new InvalidPropertyException(sprintf('Found the public method "%s", but did not find a public "%s" on class %s', $addMethodFound ? $addMethod : $removeMethod, $addMethodFound ? $removeMethod : $addMethod, $reflClass->name));
         }
     }
     return null;
 }
Exemple #16
0
    public function isChoiceSelected($choice)
    {
        $choice = FormUtil::toArrayKey($choice);

        // The value should already have been converted by value transformers,
        // otherwise we had to do the conversion on every call of this method
        if (is_array($this->vars['value'])) {
            return false !== array_search($choice, $this->vars['value'], true);
        }

        return $choice === $this->vars['value'];
    }
 public function onBindNormData(FilterDataEvent $event)
 {
     $originalData = $event->getForm()->getNormData();
     // If we are not allowed to change anything, return immediately
     if (!$this->allowAdd && !$this->allowDelete) {
         // Don't set to the snapshot as then we are switching from the
         // original object to its copy, which might break things
         $event->setData($originalData);
         return;
     }
     $form = $event->getForm();
     $data = $event->getData();
     $childPropertyPath = null;
     $parentData = null;
     $addMethod = null;
     $removeMethod = null;
     $propertyPath = null;
     $plural = null;
     if ($form->hasParent() && $form->getAttribute('property_path')) {
         $propertyPath = new PropertyPath($form->getAttribute('property_path'));
         $childPropertyPath = $propertyPath;
         $parentData = $form->getParent()->getClientData();
         $lastElement = $propertyPath->getElement($propertyPath->getLength() - 1);
         // If the property path contains more than one element, the parent
         // data is the object at the parent property path
         if ($propertyPath->getLength() > 1) {
             $parentData = $propertyPath->getParent()->getValue($parentData);
             // Property path relative to $parentData
             $childPropertyPath = new PropertyPath($lastElement);
         }
         // The plural form is the last element of the property path
         $plural = ucfirst($lastElement);
     }
     if (null === $data) {
         $data = array();
     }
     if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
         throw new UnexpectedTypeException($data, 'array or (\\Traversable and \\ArrayAccess)');
     }
     if (null !== $originalData && !is_array($originalData) && !($originalData instanceof \Traversable && $originalData instanceof \ArrayAccess)) {
         throw new UnexpectedTypeException($originalData, 'array or (\\Traversable and \\ArrayAccess)');
     }
     // Check if the parent has matching methods to add/remove items
     if ($this->mergeStrategy & self::MERGE_INTO_PARENT && is_object($parentData)) {
         $reflClass = new \ReflectionClass($parentData);
         $addMethodNeeded = $this->allowAdd && !$this->addMethod;
         $removeMethodNeeded = $this->allowDelete && !$this->removeMethod;
         // Any of the two methods is required, but not yet known
         if ($addMethodNeeded || $removeMethodNeeded) {
             $singulars = (array) FormUtil::singularify($plural);
             foreach ($singulars as $singular) {
                 // Try to find adder, but don't override preconfigured one
                 if ($addMethodNeeded) {
                     $addMethod = 'add' . $singular;
                     // False alert
                     if (!$this->isAccessible($reflClass, $addMethod, 1)) {
                         $addMethod = null;
                     }
                 }
                 // Try to find remover, but don't override preconfigured one
                 if ($removeMethodNeeded) {
                     $removeMethod = 'remove' . $singular;
                     // False alert
                     if (!$this->isAccessible($reflClass, $removeMethod, 1)) {
                         $removeMethod = null;
                     }
                 }
                 // Found all that we need. Abort search.
                 if ((!$addMethodNeeded || $addMethod) && (!$removeMethodNeeded || $removeMethod)) {
                     break;
                 }
                 // False alert
                 $addMethod = null;
                 $removeMethod = null;
             }
         }
         // Set preconfigured adder
         if ($this->allowAdd && $this->addMethod) {
             $addMethod = $this->addMethod;
             if (!$this->isAccessible($reflClass, $addMethod, 1)) {
                 throw new FormException(sprintf('The public method "%s" could not be found on class %s', $addMethod, $reflClass->getName()));
             }
         }
         // Set preconfigured remover
         if ($this->allowDelete && $this->removeMethod) {
             $removeMethod = $this->removeMethod;
             if (!$this->isAccessible($reflClass, $removeMethod, 1)) {
                 throw new FormException(sprintf('The public method "%s" could not be found on class %s', $removeMethod, $reflClass->getName()));
             }
         }
     }
     // Calculate delta between $data and the snapshot created in PRE_BIND
     $itemsToDelete = array();
     $itemsToAdd = is_object($data) ? clone $data : $data;
     if ($this->dataSnapshot) {
         foreach ($this->dataSnapshot as $originalItem) {
             foreach ($data as $key => $item) {
                 if ($item === $originalItem) {
                     // Item found, next original item
                     unset($itemsToAdd[$key]);
                     continue 2;
                 }
             }
             // Item not found, remember for deletion
             foreach ($originalData as $key => $item) {
                 if ($item === $originalItem) {
                     $itemsToDelete[$key] = $item;
                     continue 2;
                 }
             }
         }
     }
     if ($addMethod || $removeMethod) {
         // If methods to add and to remove exist, call them now, if allowed
         if ($removeMethod) {
             foreach ($itemsToDelete as $item) {
                 $parentData->{$removeMethod}($item);
             }
         }
         if ($addMethod) {
             foreach ($itemsToAdd as $item) {
                 $parentData->{$addMethod}($item);
             }
         }
         $event->setData($childPropertyPath->getValue($parentData));
     } elseif ($this->mergeStrategy & self::MERGE_NORMAL) {
         if (!$originalData) {
             // No original data was set. Set it if allowed
             if ($this->allowAdd) {
                 $originalData = $data;
             }
         } else {
             // Original data is an array-like structure
             // Add and remove items in the original variable
             if ($this->allowDelete) {
                 foreach ($itemsToDelete as $key => $item) {
                     unset($originalData[$key]);
                 }
             }
             if ($this->allowAdd) {
                 foreach ($itemsToAdd as $key => $item) {
                     if (!isset($originalData[$key])) {
                         $originalData[$key] = $item;
                     } else {
                         $originalData[] = $item;
                     }
                 }
             }
         }
         $event->setData($originalData);
     }
 }
Exemple #18
0
 public function isEmpty()
 {
     foreach ($this->children as $child) {
         if (!$child->isEmpty()) {
             return false;
         }
     }
     return FormUtil::isEmpty($this->modelData) || 0 === count($this->modelData) || $this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData);
 }
 public function noAdderRemoverData()
 {
     $data = array();
     $propertyPath = new PropertyPath('axes');
     $expectedMessage = sprintf('Neither element "axes" nor method "setAxes()" exists in class ' . '"{class}", nor could adders and removers be found based on the ' . 'guessed singulars: %s (provide a singular by suffixing the ' . 'property path with "|{singular}" to override the guesser)', implode(', ', (array) ($singulars = FormUtil::singularify('Axes'))));
     $data[] = array($propertyPath, $expectedMessage);
     $propertyPath = new PropertyPath('axes|boo');
     $expectedMessage = sprintf('Neither element "axes" nor method "setAxes()" exists in class ' . '"{class}", nor could adders and removers be found based on the ' . 'passed singular: %s', 'boo');
     $data[] = array($propertyPath, $expectedMessage);
     return $data;
 }