Author: Bernhard Schussek (bernhard.schussek@symfony-project.com)
Inheritance: implements IteratorAggregate
Esempio n. 1
0
    public function createAction()
    {
        // bind form to page model
        $page = new Page();
        $this->form->bind($this->request, $page);

        if ($this->form->isValid()) {

            try {

                // path for page
                $parent = $this->form->get('parent')->getData();
                $path = $parent . '/' . $page->name;

                // save page
                $this->dm->persist($page, $path);
                $this->dm->flush();

                // redirect with message
                $this->request->getSession()->setFlash('notice', 'Page created!');
                return $this->redirect($this->generateUrl('admin'));

            } catch (HTTPErrorException $e) {

                $path = new PropertyPath('name');
                $this->form->addError(new DataError('Name already in use.'), $path->getIterator());

            }
        }

        return $this->render('SandboxAdminBundle:Admin:create.html.twig', array('form' => $this->form));
    }
Esempio n. 2
0
 /**
  * Validates the form and its domain object
  *
  * @throws FormException  If the option "validator" was not set
  */
 public function validate()
 {
     $validator = $this->getOption('validator');
     if (null === $validator) {
         throw new MissingOptionsException('The option "validator" is required for validating', array('validator'));
     }
     // Validate the form in group "Default"
     // Validation of the data in the custom group is done by validateData(),
     // which is constrained by the Execute constraint
     if ($violations = $validator->validate($this)) {
         foreach ($violations as $violation) {
             $propertyPath = new PropertyPath($violation->getPropertyPath());
             $iterator = $propertyPath->getIterator();
             $template = $violation->getMessageTemplate();
             $parameters = $violation->getMessageParameters();
             if ($iterator->current() == 'data') {
                 $iterator->next();
                 // point at the first data element
                 $error = new DataError($template, $parameters);
             } else {
                 $error = new FieldError($template, $parameters);
             }
             $this->addError($error, $iterator);
         }
     }
 }
Esempio n. 3
0
 /**
  * Binds the form with values and files.
  *
  * This method is final because it is very easy to break a form when
  * overriding this method and adding logic that depends on $taintedFiles.
  * You should override doBind() instead where the uploaded files are
  * already merged into the data array.
  *
  * @param  array $taintedValues  The form data of the $_POST array
  * @param  array $taintedFiles   An array of uploaded files
  * @return boolean               Whether the form is valid
  */
 public final function bind($taintedValues, array $taintedFiles = null)
 {
     if (null === $taintedFiles) {
         if ($this->isMultipart() && $this->getParent() === null) {
             throw new \InvalidArgumentException('You must provide a files array for multipart forms');
         }
         $taintedFiles = array();
     }
     if (null === $taintedValues) {
         $taintedValues = array();
     }
     $this->doBind(self::deepArrayUnion($taintedValues, $taintedFiles));
     if ($this->getParent() === null) {
         if ($this->validator === null) {
             throw new FormException('A validator is required for binding. Forgot to pass it to the constructor of the form?');
         }
         if ($violations = $this->validator->validate($this, $this->getValidationGroups())) {
             // TODO: test me
             foreach ($violations as $violation) {
                 $propertyPath = new PropertyPath($violation->getPropertyPath());
                 $iterator = $propertyPath->getIterator();
                 if ($iterator->current() == 'data') {
                     $type = self::DATA_ERROR;
                     $iterator->next();
                     // point at the first data element
                 } else {
                     $type = self::FIELD_ERROR;
                 }
                 $this->addError(new FieldError($violation->getMessageTemplate(), $violation->getMessageParameters()), $iterator, $type);
             }
         }
     }
 }
Esempio n. 4
0
 public function testToString()
 {
     $path = new PropertyPath('reference.traversable[index].property');
     $this->assertEquals('reference.traversable[index].property', $path->__toString());
 }
Esempio n. 5
0
 public function testNextThrowsExceptionIfNoNextElement()
 {
     $path = new PropertyPath('property');
     $this->setExpectedException('OutOfBoundsException');
     $path->next();
 }
Esempio n. 6
0
 protected function updateProperty(&$objectOrArray, PropertyPath $propertyPath)
 {
     if (is_object($objectOrArray) && $propertyPath->isIndex()) {
         if (!$objectOrArray instanceof \ArrayAccess) {
             throw new InvalidPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \\ArrayAccess', $propertyPath->getCurrent(), get_class($objectOrArray)));
         }
         $objectOrArray[$propertyPath->getCurrent()] = $this->getData();
     } else {
         if (is_object($objectOrArray)) {
             $reflClass = new \ReflectionClass($objectOrArray);
             $setter = 'set' . ucfirst($propertyPath->getCurrent());
             $property = $propertyPath->getCurrent();
             if ($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}($this->getData());
             } else {
                 if ($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 "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
                     }
                     $objectOrArray->{$property} = $this->getData();
                 } else {
                     throw new InvalidPropertyException(sprintf('Neither element "%s" nor method "%s()" exists in class "%s"', $property, $setter, $reflClass->getName()));
                 }
             }
         } else {
             $objectOrArray[$propertyPath->getCurrent()] = $this->getData();
         }
     }
 }
Esempio n. 7
0
 public function testAddErrorMapsErrorsOntoFieldsInAnonymousGroups()
 {
     $error = new FieldError('Message');
     // path is expected to point at "address"
     $expectedPath = new PropertyPath('address');
     $expectedPathIterator = $expectedPath->getIterator();
     $field = $this->createMockField('address');
     $field->expects($this->any())->method('getPropertyPath')->will($this->returnValue(new PropertyPath('address')));
     $field->expects($this->once())->method('addError')->with($this->equalTo($error), $this->equalTo($expectedPathIterator), $this->equalTo(FieldGroup::DATA_ERROR));
     $group = new TestFieldGroup('author');
     $group2 = new TestFieldGroup('anonymous', array('property_path' => null));
     $group2->add($field);
     $group->add($group2);
     $path = new PropertyPath('address');
     $group->addError($error, $path->getIterator(), FieldGroup::DATA_ERROR);
 }
Esempio n. 8
0
 /**
  * Binds the form with values and files.
  *
  * This method is final because it is very easy to break a form when
  * overriding this method and adding logic that depends on $taintedFiles.
  * You should override doBind() instead where the uploaded files are
  * already merged into the data array.
  *
  * @param  array $taintedValues  The form data of the $_POST array
  * @param  array $taintedFiles   An array of uploaded files
  * @return boolean               Whether the form is valid
  */
 public final function bind($taintedValues, array $taintedFiles = null)
 {
     if ($taintedFiles === null) {
         if ($this->isMultipart() && $this->getParent() === null) {
             throw new \InvalidArgumentException('You must provide a files array for multipart forms');
         }
         $taintedFiles = array();
     }
     if (null === $taintedValues) {
         $taintedValues = array();
     }
     $this->doBind(self::deepArrayUnion($taintedValues, $taintedFiles));
     if ($this->getParent() === null) {
         if ($violations = $this->validator->validate($this, $this->getValidationGroups())) {
             foreach ($violations as $violation) {
                 $propertyPath = new PropertyPath($violation->getPropertyPath());
                 if ($propertyPath->getCurrent() == 'data') {
                     $type = self::DATA_ERROR;
                     $propertyPath->next();
                     // point at the first data element
                 } else {
                     $type = self::FIELD_ERROR;
                 }
                 $this->addError($violation->getMessage(), $propertyPath, $type);
             }
         }
     }
 }
Esempio n. 9
0
 /**
  * Initializes the choices and returns them
  *
  * The choices are generated from the entities. If the entities have a
  * composite identifier, the choices are indexed using ascending integers.
  * Otherwise the identifiers are used as indices.
  *
  * If the entities were passed in the "choices" option, this method
  * does not have any significant overhead. Otherwise, if a query builder
  * was passed in the "query_builder" option, this builder is now used
  * to construct a query which is executed. In the last case, all entities
  * for the underlying class are fetched from the repository.
  *
  * If the option "property" was passed, the property path in that option
  * is used as option values. Otherwise this method tries to convert
  * objects to strings using __toString().
  *
  * @return array  An array of choices
  */
 protected function getInitializedChoices()
 {
     if ($this->getOption('choices')) {
         $entities = parent::getInitializedChoices();
     } else {
         if ($qb = $this->getQueryBuilder()) {
             $entities = $qb->getQuery()->execute();
         } else {
             $class = $this->getOption('class');
             $em = $this->getOption('em');
             $entities = $em->getRepository($class)->findAll();
         }
     }
     $propertyPath = null;
     $choices = array();
     $this->entities = array();
     // The propery option defines, which property (path) is used for
     // displaying entities as strings
     if ($this->getOption('property')) {
         $propertyPath = new PropertyPath($this->getOption('property'));
     }
     foreach ($entities as $key => $entity) {
         if ($propertyPath) {
             // If the property option was given, use it
             $value = $propertyPath->getValue($entity);
         } else {
             // Otherwise expect a __toString() method in the entity
             $value = (string) $entity;
         }
         if (count($this->getIdentifierFields()) > 1) {
             // When the identifier consists of multiple field, use
             // naturally ordered keys to refer to the choices
             $choices[$key] = $value;
             $this->entities[$key] = $entity;
         } else {
             // When the identifier is a single field, index choices by
             // entity ID for performance reasons
             $id = current($this->getIdentifierValues($entity));
             $choices[$id] = $value;
             $this->entities[$id] = $entity;
         }
     }
     return $choices;
 }
Esempio n. 10
0
 /**
  * {@inheritDoc}
  */
 public function addError($message, PropertyPath $path = null, $type = null)
 {
     if ($path !== null) {
         if ($type === self::FIELD_ERROR && $path->hasNext()) {
             $path->next();
             if ($this->has($path->getCurrent()) && !$this->get($path->getCurrent())->isHidden()) {
                 $this->get($path->getCurrent())->addError($message, $path, $type);
                 return;
             }
         } else {
             if ($type === self::DATA_ERROR) {
                 $iterator = new RecursiveFieldsWithPropertyPathIterator($this);
                 $iterator = new \RecursiveIteratorIterator($iterator);
                 foreach ($iterator as $field) {
                     if (null !== ($fieldPath = $field->getPropertyPath())) {
                         $fieldPath->rewind();
                         if ($fieldPath->getCurrent() === $path->getCurrent() && !$field->isHidden()) {
                             if ($path->hasNext()) {
                                 $path->next();
                             }
                             $field->addError($message, $path, $type);
                             return;
                         }
                     }
                 }
             }
         }
     }
     parent::addError($message);
 }
Esempio n. 11
0
 public function testAddErrorMapsDataValidationErrorsOntoNestedFields()
 {
     // path is expected to point at "street"
     $expectedPath = new PropertyPath('address.street');
     $expectedPath->next();
     $field = $this->createMockField('address');
     $field->expects($this->any())->method('getPropertyPath')->will($this->returnValue(new PropertyPath('address')));
     $field->expects($this->once())->method('addError')->with($this->equalTo('Message'), $this->equalTo($expectedPath), $this->equalTo(FieldGroup::DATA_ERROR));
     $group = new FieldGroup('author');
     $group->add($field);
     $group->addError('Message', new PropertyPath('address.street'), FieldGroup::DATA_ERROR);
 }
Esempio n. 12
-1
 public function testAddErrorMapsErrorsOntoFieldsInVirtualGroups()
 {
     $error = new DataError('Message');
     // path is expected to point at "address"
     $expectedPath = new PropertyPath('address');
     $expectedPathIterator = $expectedPath->getIterator();
     $field = $this->createMockField('address');
     $field->expects($this->any())->method('getPropertyPath')->will($this->returnValue(new PropertyPath('address')));
     $field->expects($this->once())->method('addError')->with($this->equalTo($error), $this->equalTo($expectedPathIterator));
     $form = new Form('author');
     $nestedForm = new Form('nested', array('virtual' => true));
     $nestedForm->add($field);
     $form->add($nestedForm);
     $path = new PropertyPath('address');
     $form->addError($error, $path->getIterator());
 }