8000 [Form] Refactored logic to read and set values from Field to Property… · lcf/symfony@e1be4e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit e1be4e9

Browse files
Bernhard Schussekfabpot
Bernhard Schussek
authored andcommitted
[Form] Refactored logic to read and set values from Field to PropertyPath
1 parent 1fab031 commit e1be4e9

File tree

9 files changed

+581
-463
lines changed

9 files changed

+581
-463
lines changed

src/Symfony/Component/Form/Field.php

Lines changed: 3 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
* with this source code in the file LICENSE.
1212
*/
1313

14-
use Symfony\Component\Form\Exception\InvalidPropertyException;
15-
use Symfony\Component\Form\Exception\PropertyAccessDeniedException;
1614
use Symfony\Component\Form\ValueTransformer\ValueTransformerInterface;
1715
use Symfony\Component\Form\ValueTransformer\TransformationFailedException;
1816

@@ -274,7 +272,7 @@ public function getData()
274272
*
275273
* @see FieldInterface
276274
*/
277-
public function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null)
275+
public function addError($messageTemplate, array $messageParameters = array(), PropertyPathIterator $pathIterator = null, $type = null)
278276
{
279277
$this->errors[] = array($messageTemplate, $messageParameters);
280278
}
@@ -410,8 +408,7 @@ public function updateFromObject(&$objectOrArray)
410408
{
411409
// TODO throw exception if not object or array
412410
if ($this->propertyPath !== null) {
413-
$this->propertyPath->rewind();
414-
$this->setData($this->readPropertyPath($objectOrArray, $this->propertyPath));
411+
$this->setData($this->propertyPath->getValue($objectOrArray));
415412
} else {
416413
// pass object through if the property path is empty
417414
$this->setData($objectOrArray);
@@ -426,157 +423,7 @@ public function updateObject(&$objectOrArray)
426423
// TODO throw exception if not object or array
427424

428425
if ($this->propertyPath !== null) {
429-
$this->propertyPath->rewind();
430-
$this->updatePropertyPath($objectOrArray, $this->propertyPath);
431-
}
432-
}
433-
434-
/**
435-
* Recursively reads the value of the property path in the data
436-
*
437-
* @param array|object $objectOrArray An object or array
438-
* @param PropertyPath $propertyPath A property path pointing to a property
439-
* in the object/array.
440-
*/
441-
protected function readPropertyPath(&$objectOrArray, PropertyPath $propertyPath)
442-
{
443-
if (is_object($objectOrArray)) {
444-
$value = $this->readProperty($objectOrArray, $propertyPath);
445-
}
446-
// arrays need to be treated separately (due to PHP bug?)
447-
// http://bugs.php.net/bug.php?id=52133
448-
else {
449-
if (!array_key_exists($propertyPath->getCurrent(), $objectOrArray)) {
450-
$objectOrArray[$propertyPath->getCurrent()] = array();
451-
}
452-
453-
$value =& $objectOrArray[$propertyPath->getCurrent()];
454-
}
455-
456-
if ($propertyPath->hasNext()) {
457-
$propertyPath->next();
458-
459-
return $this->readPropertyPath($value, $propertyPath);
460-
} else {
461-
return $value;
462-
}
463-
}
464-
465-
protected function updatePropertyPath(&$objectOrArray, PropertyPath $propertyPath)
466-
{
467-
if ($propertyPath->hasNext()) {
468-
if (is_object($objectOrArray)) {
469-
$value = $this->readProperty($objectOrArray, $propertyPath);
470-
}
471-
// arrays need to be treated separately (due to PHP bug?)
472-
// http://bugs.php.net/bug.php?id=52133
473-
else {
474-
if (!array_key_exists($propertyPath->getCurrent(), $objectOrArray)) {
475-
$objectOrArray[$propertyPath->getCurrent()] = array();
476-
}
477-
478-
$value =& $objectOrArray[$propertyPath->getCurrent()];
479-
}
480-
481-
$propertyPath->next();
482-
483-
$this->updatePropertyPath($value, $propertyPath);
484-
} else {
485-
$this->updateProperty($objectOrArray, $propertyPath);
486-
}
487-
}
488-
489-
/**
490-
* Reads a specific element of the given data
491-
*
492-
* If the data is an array, the value at index $element is returned.
493-
*
494-
* If the data is an object, either the result of get{$element}(),
495-
* is{$element}() or the property $element is returned. If none of these
496-
* is publicly available, an exception is thrown
497-
*
498-
* @param object $object The data to read
499-
* @param string $element The element to read from the data
500-
* @return mixed The value of the element
501-
*/
502-
protected function readProperty($object, PropertyPath $propertyPath)
503-
{
504-
$camelizer = function ($path) {
505-
return preg_replace(array('/(^|_)+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $path);
506-
};
507-
508-
if ($propertyPath->isIndex()) {
509-
if (!$object instanceof \ArrayAccess) {
510-
throw new InvalidPropertyException(sprintf('Index "%s" cannot be read from object of type "%s" because it doesn\'t implement \ArrayAccess', $propertyPath->getCurrent(), get_class($object)));
511-
}
512-
513-
return $object[$propertyPath->getCurrent()];
514-
} else {
515-
$reflClass = new \ReflectionClass($object);
516-
$getter = 'get'.$camelizer($propertyPath->getCurrent());
517-
$isser = 'is'.$camelizer($propertyPath->getCurrent());
518-
$property = $propertyPath->getCurrent();
519-
520-
if ($reflClass->hasMethod($getter)) {
521-
if (!$reflClass->getMethod($getter)->isPublic()) {
522-
throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $getter, $reflClass->getName()));
523-
}
524-
525-
return $object->$getter();
526-
} else if ($reflClass->hasMethod($isser)) {
527-
if (!$reflClass->getMethod($isser)->isPublic()) {
528-
throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $isser, $reflClass->getName()));
529-
}
530-
531-
return $object->$isser();
532-
} else if ($reflClass->hasProperty($property)) {
533-
if (!$reflClass->getProperty($property)->isPublic()) {
534-
throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "get%s()" or "is%s()"?', $property, $reflClass->getName(), ucfirst($property), ucfirst($property)));
535-
}
536-
537-
return $object->$property;
538-
} else if (property_exists($object, $property)) {
539-
// needed to support \stdClass instances
540-
return $object->$property;
541-
} else {
542-
throw new InvalidPropertyException(sprintf('Neither property "%s" nor method "%s()" nor method "%s()" exists in class "%s"', $property, $getter, $isser, $reflClass->getName()));
543-
}
544-
}
545-
}
546-
547-
protected function updateProperty(&$objectOrArray, PropertyPath $propertyPath)
548-
{
549-
if (is_object($objectOrArray) && $propertyPath->isIndex()) {
550-
if (!$objectOrArray instanceof \ArrayAccess) {
551-
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)));
552-
}
553-
554-
$objectOrArray[$propertyPath->getCurrent()] = $this->getData();
555-
} else if (is_object($objectOrArray)) {
556-
$reflClass = new \ReflectionClass($objectOrArray);
557-
$setter = 'set'.ucfirst($propertyPath->getCurrent());
558-
$property = $propertyPath->getCurrent();
559-
560-
if ($reflClass->hasMethod($setter)) {
561-
if (!$reflClass->getMethod($setter)->isPublic()) {
562-
throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
563-
}
564-
565-
$objectOrArray->$setter($this->getData());
566-
} else if ($reflClass->hasProperty($property)) {
567-
if (!$reflClass->getProperty($property)->isPublic()) {
568-
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)));
569-
}
570-
571-
$objectOrArray->$property = $this->getData();
572-
} else if (property_exists($objectOrArray, $property)) {
573-
// needed to support \stdClass instances
574-
$objectOrArray->$property = $this->getData();
575-
} else {
576-
throw new InvalidPropertyException(sprintf('Neither element "%s" nor method "%s()" exists in class "%s"', $property, $setter, $reflClass->getName()));
577-
}
578-
} else {
579-
$objectOrArray[$propertyPath->getCurrent()] = $this->getData();
426+
$this->propertyPath->setValue($objectOrArray, $this->getData());
580427
}
581428
}
582429
}

src/Symfony/Component/Form/FieldGroup.php

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,18 @@ public function isValid()
393393
/**
394394
* {@inheritDoc}
395395
*/
396-
public function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null)
396+
public function addError($messageTemplate, array $messageParameters = array(), PropertyPathIterator $pathIterator = null, $type = null)
397397
{
398-
if ($path !== null) {
399-
if ($type === self::FIELD_ERROR && $path->hasNext()) {
400-
$path->next();
398+
if ($pathIterator !== null) {
399+
if ($type === self::FIELD_ERROR && $pathIterator->hasNext()) {
400+
$pathIterator->next();
401401

402-
if ($path->isProperty() && $path->getCurrent() === 'fields') {
403-
$path->next();
402+
if ($pathIterator->isProperty() && $pathIterator->current() === 'fields') {
403+
$pathIterator->next();
404404
}
405405

406-
if ($this->has($path->getCurrent()) && !$this->get($path->getCurrent())->isHidden()) {
407-
$this->get($path->getCurrent())->addError($messageTemplate, $messageParameters, $path, $type);
406+
if ($this->has($pathIterator->current()) && !$this->get($pathIterator->current())->isHidden()) {
407+
$this->get($pathIterator->current())->addError($messageTemplate, $messageParameters, $pathIterator, $type);
408408

409409
return;
410410
}
@@ -414,14 +414,12 @@ public function addError($messageTemplate, array $messageParameters = array(), P
414414

415415
foreach ($iterator as $field) {
416416
if (null !== ($fieldPath = $field->getPropertyPath())) {
417-
$fieldPath->rewind();
418-
419-
if ($fieldPath->getCurrent() === $path->getCurrent() && !$field->isHidden()) {
420-
if ($path->hasNext()) {
421-
$path->next();
417+
if ($fieldPath->getElement(0) === $pathIterator->current() && !$field->isHidden()) {
418+
if ($pathIterator->hasNext()) {
419+
$pathIterator->next();
422420
}
423421

424-
$field->addError($messageTemplate, $messageParameters, $path, $type);
422+
$field->addError($messageTemplate, $messageParameters, $pathIterator, $type);
425423

426424
return;
427425
}

src/Symfony/Component/Form/FieldInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ public function bind($taintedData);
182182
* </code>
183183
*
184184
* @param FieldInterface $field
185-
* @param PropertyPath $path
185+
* @param PropertyPathIterator $pathIterator
186186
* @param ConstraintViolation$violation
187187
*/
188-
function addError($messageTemplate, array $messageParameters = array(), PropertyPath $path = null, $type = null);
188+
function addError($messageTemplate, array $messageParameters = array(), PropertyPathIterator $pathIterator = null, $type = null);
189189

190190
/**
191191
* Returns whether the field is bound.

src/Symfony/Component/Form/Form.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,19 @@ final public function bind($taintedValues, array $taintedFiles = null)
142142

143143
if ($this->getParent() === null) {
144144
if ($violations = $this->validator->validate($this, $this->getValidationGroups())) {
145+
// TODO: test me
145146
foreach ($violations as $violation) {
146147
$propertyPath = new PropertyPath($violation->getPropertyPath());
148+
$iterator = $propertyPath->getIterator();
147149

148-
if ($propertyPath->getCurrent() == 'data') {
150+
if ($iterator->current() == 'data') {
149151
$type = self::DATA_ERROR;
150-
$propertyPath->next(); // point at the first data element
152+
$iterator->next(); // point at the first data element
151153
} else {
152154
$type = self::FIELD_ERROR;
153155
}
154156

155-
$this->addError($violation->getMessageTemplate(), $violation->getMessageParameters(), $propertyPath, $type);
157+
$this->addError($violation->getMessageTemplate(), $violation->getMessageParameters(), $iterator, $type);
156158
4281 }
157159
}
158160
}

0 commit comments

Comments
 (0)
0