Skip to content

Commit

Permalink
[Form] Reorganized code into "form extensions"
Browse files Browse the repository at this point in the history
The extension classes are now the only constructor argument of the FormFactory class. They replace the existing "type loader" classes.

    new FormFactory(array(
        new CoreExtension($validator, $storage),
        new CsrfExtension($csrfProvider),
        new DoctrineOrmExtension($em),
    ));

Together with a few upcoming commits this mechanism will make

 * extension of the form framework in bundles and
 * usage of the forms outside of Symfony2

much easier.
  • Loading branch information
webmozart committed Apr 22, 2011
1 parent a97366f commit 54e66c5
Show file tree
Hide file tree
Showing 162 changed files with 999 additions and 817 deletions.
Expand Up @@ -14,7 +14,7 @@
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\Extension\Core\ChoiceList\ArrayChoiceList;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\NoResultException;
Expand Down
Expand Up @@ -13,8 +13,8 @@

use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\DataTransformer\TransformationFailedException;
use Symfony\Component\Form\DataTransformer\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

Expand Down
Expand Up @@ -12,9 +12,9 @@
namespace Symfony\Bridge\Doctrine\Form\DataTransformer;

use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\DataTransformer\DataTransformerInterface;
use Symfony\Component\Form\DataTransformer\TransformationFailedException;
use Symfony\Component\Form\Exception\TransformationFailedException;

class EntityToIdTransformer implements DataTransformerInterface
{
Expand Down
41 changes: 41 additions & 0 deletions src/Symfony/Bridge/Doctrine/Form/DoctrineOrmExtension.php
@@ -0,0 +1,41 @@
<?php

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

namespace Symfony\Bridge\Doctrine\Form;

use Symfony\Component\Form\AbstractExtension;
use Doctrine\ORM\EntityManager;

class DoctrineOrmExtension extends AbstractExtension
{
/**
* The Doctrine 2 entity manager
* @var Doctrine\ORM\EntityManager
*/
protected $em = null;

public function __construct(EntityManager $em)
{
$this->em = $em;
}

protected function loadTypes()
{
return array(
new Type\EntityType($this->em),
);
}

protected function loadTypeGuesser()
{
return new DoctrineOrmTypeGuesser($this->em);
}
}
Expand Up @@ -3,38 +3,28 @@
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Doctrine\Form\Type\Guesser;
namespace Symfony\Bridge\Doctrine\Form;

use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\Type\Guesser\Guess;
use Symfony\Component\Form\Type\Guesser\TypeGuesserInterface;
use Symfony\Component\Form\Type\Guesser\TypeGuess;
use Symfony\Component\Form\Type\Guesser\ValueGuess;

/**
* Guesses form fields from the metadata of Doctrine 2
*
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
*/
class EntityTypeGuesser implements TypeGuesserInterface
class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
{
/**
* The Doctrine 2 entity manager
* @var Doctrine\ORM\EntityManager
*/
protected $em = null;

/**
* Constructor
*
* @param ClassMetadataFactoryInterface $metadataFactory
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
Expand Down Expand Up @@ -190,4 +180,4 @@ public function guessMaxLength($class, $property)
}
}
}
}
}
38 changes: 0 additions & 38 deletions src/Symfony/Bridge/Doctrine/Form/DoctrineTypeLoader.php

This file was deleted.

Expand Up @@ -9,15 +9,15 @@
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Doctrine\Form;
namespace Symfony\Bridge\Doctrine\Form\Type;

use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
use Symfony\Bridge\Doctrine\Form\EventListener\MergeCollectionListener;
use Symfony\Bridge\Doctrine\Form\DataTransformer\EntitiesToArrayTransformer;
use Symfony\Bridge\Doctrine\Form\DataTransformer\EntityToIdTransformer;
use Symfony\Component\Form\Type\AbstractType;
use Symfony\Component\Form\AbstractType;
use Doctrine\ORM\EntityManager;

class EntityType extends AbstractType
Expand Down
8 changes: 4 additions & 4 deletions src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml
Expand Up @@ -38,7 +38,7 @@
<parameter key="doctrine.orm.proxy_cache_warmer.class">Symfony\Bundle\DoctrineBundle\CacheWarmer\ProxyCacheWarmer</parameter>

<!-- form field factory guesser -->
<parameter key="form.guesser.doctrine.class">Symfony\Bridge\Doctrine\Form\Type\Guesser\EntityTypeGuesser</parameter>
<parameter key="form.type_guesser.doctrine.class">Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser</parameter>
</parameters>

<services>
Expand All @@ -55,12 +55,12 @@
<argument type="service" id="service_container" />
</service>

<service id="form.guesser.doctrine" class="%form.guesser.doctrine.class%" public="false">
<tag name="form.guesser" />
<service id="form.type_guesser.doctrine" class="%form.type_guesser.doctrine.class%">
<tag name="form.type_guesser" />
<argument type="service" id="doctrine.orm.entity_manager" />
</service>

<service id="form.type.entity" class="Symfony\Bridge\Doctrine\Form\EntityType">
<service id="form.type.entity" class="Symfony\Bridge\Doctrine\Form\Type\EntityType">
<tag name="form.type" alias="entity" />
<argument type="service" id="doctrine.orm.entity_manager" />
</service>
Expand Down

This file was deleted.

Expand Up @@ -15,32 +15,36 @@
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
* Adds all services with the tag "form.type" as argument
* to the "form.type.loader" service
* Adds all services with the tags "form.type" and "form.type_guesser" as
* arguments of the "form.extension" service
*
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
*/
class AddFormTypesPass implements CompilerPassInterface
class FormPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('form.type.loader')) {
if (!$container->hasDefinition('form.extension')) {
return;
}

// Builds an array with service IDs as keys and tag aliases as values
$types = array();
$tags = $container->findTaggedServiceIds('form.type');

foreach ($tags as $serviceId => $arguments) {
$alias = isset($arguments[0]['alias'])
? $arguments[0]['alias']
foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) {
$alias = isset($tag[0]['alias'])
? $tag[0]['alias']
: $serviceId;

// Flip, because we want tag aliases (= type identifiers) as keys
$types[$alias] = $serviceId;
}

$container->getDefinition('form.type.loader')->replaceArgument(1, $types);
$container->getDefinition('form.extension')->replaceArgument(1, $types);

// Find all services annotated with "form.type_guesser"
$guessers = array_keys($container->findTaggedServiceIds('form.type_guesser'));

$container->getDefinition('form.extension')->replaceArgument(2, $guessers);
}
}
Expand Up @@ -11,32 +11,7 @@

namespace Symfony\Bundle\FrameworkBundle\Form;

use Symfony\Component\Form\Type\Loader\TypeLoaderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class ContainerAwareTypeLoader implements TypeLoaderInterface
{
private $container;

private $serviceIds;

public function __construct(ContainerInterface $container, array $serviceIds)
{
$this->container = $container;
$this->serviceIds = $serviceIds;
}

public function getType($identifier)
{
if (!isset($this->serviceIds[$identifier])) {
throw new \InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $identifier));
}

return $this->container->get($this->serviceIds[$identifier]);
}

public function hasType($identifier)
{
return isset($this->serviceIds[$identifier]);
}
}
6 changes: 2 additions & 4 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Expand Up @@ -12,8 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle;

use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddFormTypesPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddFormGuessersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RoutingResolverPass;
Expand Down Expand Up @@ -78,8 +77,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new RegisterKernelListenersPass());
$container->addCompilerPass(new TemplatingPass());
$container->addCompilerPass(new AddConstraintValidatorsPass());
$container->addCompilerPass(new AddFormTypesPass());
$container->addCompilerPass(new AddFormGuessersPass());
$container->addCompilerPass(new FormPass());
$container->addCompilerPass(new AddClassesToCachePass());
$container->addCompilerPass(new AddClassesToAutoloadMapPass());
$container->addCompilerPass(new TranslatorPass());
Expand Down

0 comments on commit 54e66c5

Please sign in to comment.