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); }
public function testNextThrowsExceptionIfNoNextElement() { $path = new PropertyPath('property'); $this->setExpectedException('OutOfBoundsException'); $path->next(); }
/** * 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 The form data of the $_FILES array * @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(); } else { $taintedFiles = self::convertFileInformation(self::fixPhpFilesArray($taintedFiles)); } $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); } } } }
/** * {@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); }