refactored Doctrine Bridge

* added a RegistryInterface

 * changed all classes to depend on the Registry instead of a specific EntityManager

This is more consistent as the validator already took the registry and this allows
to use any entity manager in Forms.
This commit is contained in:
Fabien Potencier 2011-06-08 08:07:12 +02:00
parent 84b25b1626
commit fbf36957e6
15 changed files with 308 additions and 225 deletions

View File

@ -9,6 +9,10 @@ timeline closely anyway.
beta4 to beta5
--------------
* The `em` option of the Doctrine `EntityType` class now takes the entity
manager name instead of the EntityManager instance. If you don't pass this
option, the default Entity Manager will be used as before.
* In the Console component: `Command::getFullname()` and
`Command::getNamespace()` have been removed (`Command::getName()` behavior
is now the same as the old `Command::getFullname()`).

View File

@ -12,30 +12,26 @@
namespace Symfony\Bridge\Doctrine\Form;
use Symfony\Component\Form\AbstractExtension;
use Doctrine\ORM\EntityManager;
use Symfony\Bridge\Doctrine\RegistryInterface;
class DoctrineOrmExtension extends AbstractExtension
{
/**
* The Doctrine 2 entity manager
* @var Doctrine\ORM\EntityManager
*/
protected $em = null;
protected $registry;
public function __construct(EntityManager $em)
public function __construct(RegistryInterface $registry)
{
$this->em = $em;
$this->registry = $registry;
}
protected function loadTypes()
{
return array(
new Type\EntityType($this->em),
new Type\EntityType($this->registry),
);
}
protected function loadTypeGuesser()
{
return new DoctrineOrmTypeGuesser($this->em);
return new DoctrineOrmTypeGuesser($this->registry);
}
}

View File

@ -15,29 +15,18 @@ 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\Bridge\Doctrine\RegistryInterface;
class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
{
/**
* The Doctrine 2 entity manager
* @var Doctrine\ORM\EntityManager
*/
protected $em = null;
protected $registry;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
private $cache;
/**
* Returns whether Doctrine 2 metadata exists for that class
*
* @return Boolean
*/
protected function isMappedClass($class)
public function __construct(RegistryInterface $registry)
{
return !$this->em->getConfiguration()->getMetadataDriverImpl()->isTransient($class);
$this->registry = $registry;
$this->cache = array();
}
/**
@ -45,94 +34,45 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
*/
public function guessType($class, $property)
{
if ($this->isMappedClass($class)) {
$metadata = $this->em->getClassMetadata($class);
if ($metadata->hasAssociation($property)) {
$multiple = $metadata->isCollectionValuedAssociation($property);
$mapping = $metadata->getAssociationMapping($property);
return new TypeGuess(
'entity',
array(
'em' => $this->em,
'class' => $mapping['targetEntity'],
'multiple' => $multiple,
),
Guess::HIGH_CONFIDENCE
);
} else {
switch ($metadata->getTypeOfField($property))
{
// case 'array':
// return new TypeGuess(
// 'Collection',
// array(),
// Guess::HIGH_CONFIDENCE
// );
case 'boolean':
return new TypeGuess(
'checkbox',
array(),
Guess::HIGH_CONFIDENCE
);
case 'datetime':
case 'vardatetime':
case 'datetimetz':
return new TypeGuess(
'datetime',
array(),
Guess::HIGH_CONFIDENCE
);
case 'date':
return new TypeGuess(
'date',
array(),
Guess::HIGH_CONFIDENCE
);
case 'decimal':
case 'float':
return new TypeGuess(
'number',
array(),
Guess::MEDIUM_CONFIDENCE
);
case 'integer':
case 'bigint':
case 'smallint':
return new TypeGuess(
'integer',
array(),
Guess::MEDIUM_CONFIDENCE
);
case 'string':
return new TypeGuess(
'text',
array(),
Guess::MEDIUM_CONFIDENCE
);
case 'text':
return new TypeGuess(
'textarea',
array(),
Guess::MEDIUM_CONFIDENCE
);
case 'time':
return new TypeGuess(
'time',
array(),
Guess::HIGH_CONFIDENCE
);
// case 'object': ???
}
}
if (!$metadata = $this->getMetadata($class)) {
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
}
return new TypeGuess(
'text',
array(),
Guess::LOW_CONFIDENCE
);
if ($metadata->hasAssociation($property)) {
$multiple = $metadata->isCollectionValuedAssociation($property);
$mapping = $metadata->getAssociationMapping($property);
return new TypeGuess('entity', array('em' => $this->em, 'class' => $mapping['targetEntity'], 'multiple' => $multiple), Guess::HIGH_CONFIDENCE);
}
switch ($metadata->getTypeOfField($property))
{
//case 'array':
// return new TypeGuess('Collection', array(), Guess::HIGH_CONFIDENCE);
case 'boolean':
return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE);
case 'datetime':
case 'vardatetime':
case 'datetimetz':
return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE);
case 'date':
return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE);
case 'decimal':
case 'float':
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
case 'integer':
case 'bigint':
case 'smallint':
return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
case 'string':
return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
case 'text':
return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE);
case 'time':
return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE);
default:
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
}
}
/**
@ -140,22 +80,12 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
*/
public function guessRequired($class, $property)
{
if ($this->isMappedClass($class)) {
$metadata = $this->em->getClassMetadata($class);
if ($metadata->hasField($property)) {
if (!$metadata->isNullable($property)) {
return new ValueGuess(
true,
Guess::HIGH_CONFIDENCE
);
}
return new ValueGuess(
false,
Guess::MEDIUM_CONFIDENCE
);
if ($metadata = $this->getMetadata($class) && $metadata->hasField($property)) {
if (!$metadata->isNullable($property)) {
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
}
return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE);
}
}
@ -164,19 +94,11 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
*/
public function guessMaxLength($class, $property)
{
if ($this->isMappedClass($class)) {
$metadata = $this->em->getClassMetadata($class);
if ($metadata = $this->getMetadata($class) && !$metadata->hasAssociation($property)) {
$mapping = $metadata->getFieldMapping($property);
if (!$metadata->hasAssociation($property)) {
$mapping = $metadata->getFieldMapping($property);
if (isset($mapping['length'])) {
return new ValueGuess(
$mapping['length'],
Guess::HIGH_CONFIDENCE
);
}
if (isset($mapping['length'])) {
return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
}
}
}
@ -186,6 +108,24 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
*/
public function guessMinLength($class, $property)
{
return;
}
/**
* Returns whether Doctrine 2 metadata exists for that class
*
* @return Boolean
*/
protected function getMetadata($class)
{
if (array_key_exists($class, $this->cache)) {
return $this->cache[$class];
}
$this->cache[$class] = null;
foreach ($this->registry->getEntityManagers() as $em) {
if ($em->getConfiguration()->getMetadataDriverImpl()->isTransient($class)) {
return $this->cache[$class] = $em->getClassMetadata($class);
}
}
}
}

View File

@ -13,20 +13,20 @@ namespace Symfony\Bridge\Doctrine\Form\Type;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Bridge\Doctrine\RegistryInterface;
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\AbstractType;
use Doctrine\ORM\EntityManager;
class EntityType extends AbstractType
{
private $em;
protected $registry;
public function __construct(EntityManager $em)
public function __construct(RegistryInterface $registry)
{
$this->em = $em;
$this->registry = $registry;
}
public function buildForm(FormBuilder $builder, array $options)
@ -46,7 +46,7 @@ class EntityType extends AbstractType
$defaultOptions = array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => null,
'class' => null,
'property' => null,
'query_builder' => null,
@ -60,7 +60,7 @@ class EntityType extends AbstractType
if (!isset($options['choice_list'])) {
$defaultOptions['choice_list'] = new EntityChoiceList(
$options['em'],
$this->registry->getEntityManager($options['em']),
$options['class'],
$options['property'],
$options['query_builder'],
@ -80,4 +80,4 @@ class EntityType extends AbstractType
{
return 'entity';
}
}
}

View File

@ -0,0 +1,127 @@
<?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\Bridge\Doctrine;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
/**
* References Doctrine connections and entity managers.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface RegistryInterface
{
/**
* Gets the default connection name.
*
* @return string The default connection name
*/
function getDefaultConnectionName();
/**
* Gets the named connection.
*
* @param string $name The connection name (null for the default one)
*
* @return Connection
*/
function getConnection($name = null);
/**
* Gets an array of all registered connections
*
* @return array An array of Connection instances
*/
function getConnections();
/**
* Gets all connection names.
*
* @return array An array of connection names
*/
function getConnectionNames();
/**
* Gets the default entity manager name.
*
* @return string The default entity manager name
*/
function getDefaultEntityManagerName();
/**
* Gets a named entity manager.
*
* @param string $name The entity manager name (null for the default one)
*
* @return EntityManager
*/
function getEntityManager($name = null);
/**
* Gets an array of all registered entity managers
*
* @return array An array of EntityManager instances
*/
function getEntityManagers();
/**
* Resets a named entity manager.
*
* This method is useful when an entity manager has been closed
* because of a rollbacked transaction AND when you think that
* it makes sense to get a new one to replace the closed one.
*
* Be warned that you will get a brand new entity manager as
* the existing one is not useable anymore. This means that any
* other object with a dependency on this entity manager will
* hold an obsolete reference. You can inject the registry instead
* to avoid this problem.
*
* @param string $name The entity manager name (null for the default one)
*
* @return EntityManager
*/
function resetEntityManager($name = null);
/**
* Resolves a registered namespace alias to the full namespace.
*
* This method looks for the alias in all registered entity managers.
*
* @param string $alias The alias
*
* @return string The full namespace
*
* @see Configuration::getEntityNamespace
*/
function getEntityNamespace($alias);
/**
* Gets all connection names.
*
* @return array An array of connection names
*/
function getEntityManagerNames();
/**
* Gets the EntityRepository for an entity.
*
* @param string $entityName The name of the entity.
* @param string $entityManagerNAme The entity manager name (null for the default one)
*
* @return Doctrine\ORM\EntityRepository
*/
function getRepository($entityName, $entityManagerName = null);
}

View File

@ -17,7 +17,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Constraint for the Unique Entity validator
*
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class UniqueEntity extends Constraint
@ -25,12 +25,12 @@ class UniqueEntity extends Constraint
public $message = 'This value is already used.';
public $em = null;
public $fields = array();
public function getRequiredOptions()
{
return array('fields');
}
/**
* The validator must be defined as a service with this name.
*
@ -40,7 +40,7 @@ class UniqueEntity extends Constraint
{
return 'doctrine.orm.validator.unique';
}
/**
* {@inheritDoc}
*/
@ -48,9 +48,9 @@ class UniqueEntity extends Constraint
{
return self::CLASS_CONSTRAINT;
}
public function getDefaultOption()
{
return 'fields';
}
}
}

View File

@ -11,7 +11,7 @@
namespace Symfony\Bridge\Doctrine\Validator\Constraints;
use Symfony\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
@ -19,24 +19,24 @@ use Symfony\Component\Validator\ConstraintValidator;
/**
* Unique Entity Validator checks if one or a set of fields contain unique values.
*
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class UniqueEntityValidator extends ConstraintValidator
{
/**
* @var Registry
* @var RegistryInterface
*/
private $registry;
/**
* @param Registry $registry
* @param RegistryInterface $registry
*/
public function __construct(Registry $registry)
public function __construct(RegistryInterface $registry)
{
$this->registry = $registry;
}
/**
* @param object $entity
* @param Constraint $constraint
@ -47,35 +47,37 @@ class UniqueEntityValidator extends ConstraintValidator
if (!is_array($constraint->fields) && !is_string($constraint->fields)) {
throw new UnexpectedTypeException($constraint->fields, 'array');
}
$fields = (array)$constraint->fields;
if (count($constraint->fields) == 0) {
throw new ConstraintDefinitionException("At least one field has to specified.");
}
$em = $this->registry->getEntityManager($constraint->em);
$className = $this->context->getCurrentClass();
$class = $em->getClassMetadata($className);
$criteria = array();
foreach ($fields as $fieldName) {
if (!isset($class->reflFields[$fieldName])) {
throw new ConstraintDefinitionException("Only field names mapped by Doctrine can be validated for uniqueness.");
}
$criteria[$fieldName] = $class->reflFields[$fieldName]->getValue($entity);
}
$repository = $em->getRepository($className);
$result = $repository->findBy($criteria);
if (count($result) > 0 && $result[0] !== $entity) {
$oldPath = $this->context->getPropertyPath();
$this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath . "." . $fields[0]);
$this->context->addViolation($constraint->message, array(), $criteria[$constraint->fields[0]]);
$this->context->setPropertyPath($oldPath);
}
return true; // all true, we added the violation already!
}
}
}

View File

@ -11,7 +11,7 @@
namespace Symfony\Bundle\DoctrineBundle\CacheWarmer;
use Symfony\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
/**
@ -29,9 +29,9 @@ class ProxyCacheWarmer implements CacheWarmerInterface
/**
* Constructor.
*
* @param Registry $registry The Doctrine registry
* @param RegistryInterface $registry A RegistryInterface instance
*/
public function __construct(Registry $registry)
public function __construct(RegistryInterface $registry)
{
$this->registry = $registry;
}

View File

@ -15,7 +15,7 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\DoctrineBundle\Logger\DbalLogger;
use Symfony\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
/**
* DoctrineDataCollector.
@ -28,7 +28,7 @@ class DoctrineDataCollector extends DataCollector
private $managers;
private $logger;
public function __construct(Registry $registry, DbalLogger $logger = null)
public function __construct(RegistryInterface $registry, DbalLogger $logger = null)
{
$this->connections = $registry->getConnectionNames();
$this->managers = $registry->getEntityManagerNames();

View File

@ -11,7 +11,7 @@
namespace Symfony\Bundle\DoctrineBundle\Mapping;
use Symfony\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Doctrine\ORM\Tools\EntityRepositoryGenerator;
use Doctrine\ORM\Mapping\ClassMetadata;
@ -31,9 +31,9 @@ class MetadataFactory
/**
* Constructor.
*
* @param Registry $registry A Registry instance
* @param RegistryInterface $registry A RegistryInterface instance
*/
public function __construct(Registry $registry)
public function __construct(RegistryInterface $registry)
{
$this->registry = $registry;
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\DoctrineBundle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
@ -21,7 +22,7 @@ use Doctrine\ORM\ORMException;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Registry
class Registry implements RegistryInterface
{
private $container;
private $connections;
@ -203,7 +204,6 @@ class Registry
return $this->entityManagers;
}
/**
* Gets the EntityRepository for an entity.
*

View File

@ -49,12 +49,12 @@
<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" />
<argument type="service" id="doctrine" />
</service>
<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" />
<argument type="service" id="doctrine" />
</service>
<service id="doctrine.orm.configuration" class="%doctrine.orm.configuration.class%" abstract="true" public="false" />

View File

@ -32,7 +32,7 @@ abstract class DoctrineOrmTestCase extends \PHPUnit_Framework_TestCase
/**
* @return EntityManager
*/
public static function createTestEntityManager($paths = array())
static public function createTestEntityManager($paths = array())
{
$config = new \Doctrine\ORM\Configuration();
$config->setAutoGenerateProxyClasses(true);

View File

@ -70,7 +70,7 @@ class EntityTypeTest extends TypeTestCase
protected function getExtensions()
{
return array_merge(parent::getExtensions(), array(
new DoctrineOrmExtension($this->em),
new DoctrineOrmExtension($this->createRegistryMock('default', $this->em)),
));
}
@ -93,7 +93,7 @@ class EntityTypeTest extends TypeTestCase
// $this->persist(array($entity1, $entity2));
//
// $field = $this->factory->createNamed('entity', 'name', null, array(
// 'em' => $this->em,
// 'em' => 'default',
// 'class' => self::SINGLE_IDENT_CLASS,
// 'required' => false,
// 'property' => 'name'
@ -109,7 +109,7 @@ class EntityTypeTest extends TypeTestCase
public function testConfigureQueryBuilderWithNonQueryBuilderAndNonClosure()
{
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'query_builder' => new \stdClass(),
));
@ -121,7 +121,7 @@ class EntityTypeTest extends TypeTestCase
public function testConfigureQueryBuilderWithClosureReturningNonQueryBuilder()
{
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'query_builder' => function () {
return new \stdClass();
@ -135,7 +135,7 @@ class EntityTypeTest extends TypeTestCase
{
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->setData(null);
@ -149,7 +149,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => true,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->setData(null);
@ -163,7 +163,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->setData(null);
@ -177,7 +177,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => true,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->bind(null);
@ -191,7 +191,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->bind(null);
@ -204,7 +204,7 @@ class EntityTypeTest extends TypeTestCase
{
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
));
$field->bind(null);
@ -223,7 +223,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'property' => 'name',
));
@ -245,7 +245,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_IDENT_CLASS,
'property' => 'name',
));
@ -269,7 +269,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'property' => 'name',
));
@ -294,7 +294,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'property' => 'name',
));
@ -325,7 +325,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_IDENT_CLASS,
'property' => 'name',
));
@ -351,7 +351,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_IDENT_CLASS,
'property' => 'name',
));
@ -381,7 +381,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => true,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'property' => 'name',
));
@ -407,7 +407,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => true,
'expanded' => true,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'property' => 'name',
));
@ -437,7 +437,7 @@ class EntityTypeTest extends TypeTestCase
$this->persist(array($entity1, $entity2, $entity3));
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
// not all persisted entities should be displayed
'choices' => array($entity1, $entity2),
@ -461,7 +461,7 @@ class EntityTypeTest extends TypeTestCase
$this->persist(array($entity1, $entity2, $entity3));
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'choices' => array($entity1, $entity2),
'property' => 'name',
@ -482,7 +482,7 @@ class EntityTypeTest extends TypeTestCase
$this->persist(array($entity1, $entity2, $entity3));
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_IDENT_CLASS,
'choices' => array($entity1, $entity2),
'property' => 'name',
@ -505,7 +505,7 @@ class EntityTypeTest extends TypeTestCase
$repository = $this->em->getRepository(self::SINGLE_IDENT_CLASS);
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'query_builder' => $repository->createQueryBuilder('e')
->where('e.id IN (1, 2)'),
@ -527,7 +527,7 @@ class EntityTypeTest extends TypeTestCase
$this->persist(array($entity1, $entity2, $entity3));
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_IDENT_CLASS,
'query_builder' => function ($repository) {
return $repository->createQueryBuilder('e')
@ -551,7 +551,7 @@ class EntityTypeTest extends TypeTestCase
$this->persist(array($entity1, $entity2, $entity3));
$field = $this->factory->createNamed('entity', 'name', null, array(
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_IDENT_CLASS,
'query_builder' => function ($repository) {
return $repository->createQueryBuilder('e')
@ -575,7 +575,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::SINGLE_STRING_IDENT_CLASS,
'property' => 'name',
));
@ -596,7 +596,7 @@ class EntityTypeTest extends TypeTestCase
$field = $this->factory->createNamed('entity', 'name', null, array(
'multiple' => false,
'expanded' => false,
'em' => $this->em,
'em' => 'default',
'class' => self::COMPOSITE_STRING_IDENT_CLASS,
'property' => 'name',
));
@ -608,4 +608,15 @@ class EntityTypeTest extends TypeTestCase
$this->assertEquals($entity1, $field->getData());
$this->assertEquals(0, $field->getClientData());
}
protected function createRegistryMock($name, $em)
{
$registry = $this->getMock('Symfony\Bridge\Doctrine\RegistryInterface');
$registry->expects($this->any())
->method('getEntityManager')
->with($this->equalTo($name))
->will($this->returnValue($em));
return $registry;
}
}

View File

@ -27,14 +27,15 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
{
protected function createRegistryMock($entityManagerName, $em)
{
$registry = $this->getMock('Symfony\Bundle\DoctrineBundle\Registry', array(), array(), '', false);
$registry = $this->getMock('Symfony\Bridge\Doctrine\RegistryInterface');
$registry->expects($this->any())
->method('getEntityManager')
->with($this->equalTo($entityManagerName))
->will($this->returnValue($em));
return $registry;
}
protected function createMetadataFactoryMock($metadata)
{
$metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface');
@ -42,9 +43,10 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
->method('getClassMetadata')
->with($this->equalTo($metadata->name))
->will($this->returnValue($metadata));
return $metadataFactory;
}
protected function createValidatorFactory($uniqueValidator)
{
$validatorFactory = $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface');
@ -52,9 +54,10 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
->method('getInstance')
->with($this->isInstanceOf('Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity'))
->will($this->returnValue($uniqueValidator));
return $validatorFactory;
}
/**
* This is a functinoal test as there is a large integration necessary to get the validator working.
*/
@ -66,38 +69,38 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$schemaTool->createSchema(array(
$em->getClassMetadata('Symfony\Tests\Bridge\Doctrine\Form\Fixtures\SingleIdentEntity')
));
$entity1 = new SingleIdentEntity(1, 'Foo');
$registry = $this->createRegistryMock($entityManagerName, $em);
$uniqueValidator = new UniqueEntityValidator($registry);
$metadata = new ClassMetadata('Symfony\Tests\Bridge\Doctrine\Form\Fixtures\SingleIdentEntity');
$metadata->addConstraint(new UniqueEntity(array('fields' => array('name'), 'em' => $entityManagerName)));
$metadataFactory = $this->createMetadataFactoryMock($metadata);
$validatorFactory = $this->createValidatorFactory($uniqueValidator);
$validator = new Validator($metadataFactory, $validatorFactory);
$violationsList = $validator->validate($entity1);
$this->assertEquals(0, $violationsList->count(), "No violations found on entity before it is saved to the database.");
$em->persist($entity1);
$em->flush();
$violationsList = $validator->validate($entity1);
$this->assertEquals(0, $violationsList->count(), "No violations found on entity after it was saved to the database.");
$entity2 = new SingleIdentEntity(2, 'Foo');
$violationsList = $validator->validate($entity2);
$this->assertEquals(1, $violationsList->count(), "No violations found on entity after it was saved to the database.");
$violation = $violationsList[0];
$this->assertEquals('This value is already used.', $violation->getMessage());
$this->assertEquals('name', $violation->getPropertyPath());
$this->assertEquals('Foo', $violation->getInvalidValue());
}
}
}