Skip to content

Commit

Permalink
merged branch marcw/issue-1746 (PR #1758)
Browse files Browse the repository at this point in the history
Commits
-------

2e024f8 [Form] CollectionType now checks for data_class parameter instead of only class.
0327beb [Form] Added ObjectFactoryListener. Fixes #1746.

Discussion
----------

[Form] Added ObjectFactoryListener. Fixes #1746.

---------------------------------------------------------------------------

by marcw at 2011/07/21 09:32:17 -0700

This patch also fixes a validation issue because it was impossible for the validator to validate an array.

---------------------------------------------------------------------------

by stof at 2011/07/21 09:47:46 -0700

yeah, using the data_class of the prototype would be great
  • Loading branch information
fabpot committed Jul 22, 2011
2 parents d96c152 + 2e024f8 commit 49dda53
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
@@ -0,0 +1,66 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Core\EventListener;

use Symfony\Component\Form\Event\FilterDataEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Based on scalar values, this class instanciates object and hydrate them.
*
* @author Marc Weistroff <marc.weistroff@sensio.com>
*/
class ObjectFactoryListener implements EventSubscriberInterface
{
private $class;

/**
* __construct
*
* @param string $class FQCN class
*/
public function __construct($class)
{
$this->class = $class;
}

static public function getSubscribedEvents()
{
return array(
FormEvents::BIND_NORM_DATA => 'onBindNormData',
);
}

public function onBindNormData(FilterDataEvent $event)
{
$data = $event->getData();

foreach ($data as $k => $array) {
if (!is_array($array)) {
continue;
}

$object = new $this->class();
foreach ($array as $key => $value) {
$path = new PropertyPath($key);
$path->setValue($object, $value);
}

$data[$k] = $object;
}

$event->setData($data);
}
}

Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\Form\Extension\Core\EventListener\ObjectFactoryListener;

class CollectionType extends AbstractType
{
Expand All @@ -29,6 +30,13 @@ public function buildForm(FormBuilder $builder, array $options)
$builder->setAttribute('prototype', $prototype);
}

$dataClass = isset($options['options']['data_class']) ? $options['options']['data_class'] : null;
if ($dataClass || $options['class']) {
$class = $dataClass ? $dataClass : $options['class'];
$listener = new ObjectFactoryListener($class);
$builder->addEventSubscriber($listener);
}

$listener = new ResizeFormListener(
$builder->getFormFactory(),
$options['type'],
Expand Down Expand Up @@ -70,6 +78,7 @@ public function getDefaultOptions(array $options)
'prototype' => true,
'type' => 'text',
'options' => array(),
'class' => null,
);
}

Expand Down
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\Form\CollectionForm;
use Symfony\Component\Form\Form;
use Symfony\Tests\Component\Form\Fixtures\AuthorType;

class CollectionFormTest extends TypeTestCase
{
Expand Down Expand Up @@ -141,4 +142,40 @@ public function testPrototypeMultipartPropagation()

$this->assertTrue($form->createView()->get('multipart'));
}

public function testObjectsAreCreated()
{
$form = $this->factory
->create('collection', null, array(
'type' => new AuthorType(),
'allow_add' => true,
'class' => 'Symfony\Tests\Component\Form\Fixtures\Author',
))
;

$data = array(array('last_name' => 'Foo'), array('last_name' => 'Bar'));
$form->bind($data);
$bound = $form->getData();
$this->assertEquals(2, count($bound));
$this->assertInstanceOf('Symfony\Tests\Component\Form\Fixtures\Author', $bound[0]);
$this->assertInstanceOf('Symfony\Tests\Component\Form\Fixtures\Author', $bound[1]);
$this->assertEquals('Foo', $bound[0]->getLastName());
$this->assertEquals('Bar', $bound[1]->getLastName());
}

public function testObjectsAreCreatedWithDataClassOption()
{
$form = $this->factory
->create('collection', null, array(
'type' => new AuthorType(),
'allow_add' => true,
'options' => array('data_class' => 'Symfony\Tests\Component\Form\Fixtures\Author')
))
;

$data = array(array('last_name' => 'Foo'), array('last_name' => 'Bar'));
$form->bind($data);
$bound = $form->getData();
$this->assertInstanceOf('Symfony\Tests\Component\Form\Fixtures\Author', $bound[0]);
}
}
24 changes: 24 additions & 0 deletions tests/Symfony/Tests/Component/Form/Fixtures/AuthorType.php
@@ -0,0 +1,24 @@
<?php

namespace Symfony\Tests\Component\Form\Fixtures;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class AuthorType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('last_name', 'text')
;
}

public function getName()
{
return 'author';
}
}

0 comments on commit 49dda53

Please sign in to comment.