merged 2.0 branch

This commit is contained in:
Fabien Potencier 2011-09-04 09:28:37 +02:00
commit e7b2d2d659
25 changed files with 322 additions and 65 deletions

View File

@ -57,7 +57,8 @@ class EntitiesToArrayTransformer implements DataTransformerInterface
}
} else {
foreach ($collection as $entity) {
$array[] = current($this->choiceList->getIdentifierValues($entity));
$value = current($this->choiceList->getIdentifierValues($entity));
$array[] = is_numeric($value) ? (int) $value : $value;
}
}

View File

@ -23,7 +23,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
*/
class UniqueEntity extends Constraint
{
public $message = 'This value is already used.';
public $message = 'This value is already used';
public $em = null;
public $fields = array();

View File

@ -75,13 +75,19 @@ class UniqueEntityValidator extends ConstraintValidator
$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[$fields[0]]);
$this->context->setPropertyPath($oldPath);
/* If no entity matched the query criteria or a single entity matched,
* which is the same as the entity being validated, the criteria is
* unique.
*/
if (0 == count($result) || (1 == count($result) && $entity === $result[0])) {
return true;
}
$oldPath = $this->context->getPropertyPath();
$this->context->setPropertyPath( empty($oldPath) ? $fields[0] : $oldPath.".".$fields[0]);
$this->context->addViolation($constraint->message, array(), $criteria[$fields[0]]);
$this->context->setPropertyPath($oldPath);
return true; // all true, we added the violation already!
}
}

View File

@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Finder\Finder;
/**
* Command that places bundle web assets into a given directory.
@ -85,7 +86,8 @@ EOT
$filesystem->symlink($originDir, $targetDir);
} else {
$filesystem->mkdir($targetDir, 0777);
$filesystem->mirror($originDir, $targetDir);
// We use a custom iterator to ignore VCS files
$filesystem->mirror($originDir, $targetDir, Finder::create()->in($originDir));
}
}
}

View File

@ -71,6 +71,38 @@ class ContainerAwareEventDispatcher extends EventDispatcher
$this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
}
/**
* @see EventDispatcherInterface::hasListeners
*/
public function hasListeners($eventName = null)
{
if (null === $eventName) {
return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners);
}
if (isset($this->listenerIds[$eventName])) {
return true;
}
return parent::hasListeners($eventName);
}
/**
* @see EventDispatcherInterface::getListeners
*/
public function getListeners($eventName = null)
{
if (null === $eventName) {
foreach ($this->listenerIds as $serviceEventName => $listners) {
$this->lazyLoad($serviceEventName);
}
} else {
$this->lazyLoad($eventName);
}
return parent::getListeners($eventName);
}
/**
* {@inheritDoc}
*
@ -80,6 +112,21 @@ class ContainerAwareEventDispatcher extends EventDispatcher
* @throws \InvalidArgumentException if the service is not defined
*/
public function dispatch($eventName, Event $event = null)
{
$this->lazyLoad($eventName);
parent::dispatch($eventName, $event);
}
/**
* Lazily loads listeners for this event from the dependency injection
* container.
*
* @param string $eventName The name of the event to dispatch. The name of
* the event is the name of the method that is
* invoked on listeners.
*/
protected function lazyLoad($eventName)
{
if (isset($this->listenerIds[$eventName])) {
foreach ($this->listenerIds[$eventName] as $args) {
@ -97,7 +144,5 @@ class ContainerAwareEventDispatcher extends EventDispatcher
$this->listeners[$eventName][$key] = $listener;
}
}
parent::dispatch($eventName, $event);
}
}

View File

@ -142,6 +142,30 @@
<source>This value should be a valid number</source>
<target>Cette valeur doit être un nombre</target>
</trans-unit>
<trans-unit id="36">
<source>This file is not a valid image</source>
<target>Ce fichier n'est pas une image valide</target>
</trans-unit>
<trans-unit id="37">
<source>This is not a valid IP address</source>
<target>Cette adresse IP n'est pas valide</target>
</trans-unit>
<trans-unit id="38">
<source>This value is not a valid language</source>
<target>Cette langue n'est pas valide</target>
</trans-unit>
<trans-unit id="39">
<source>This value is not a valid locale</source>
<target>Ce paramètre régional n'est pas valide</target>
</trans-unit>
<trans-unit id="40">
<source>This value is not a valid country</source>
<target>Ce pays n'est pas valide</target>
</trans-unit>
<trans-unit id="41">
<source>This value is already used</source>
<target>Cette valeur est déjà utilisée</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -122,6 +122,50 @@ class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
$dispatcher->dispatch('onEvent');
}
public function testHasListenersOnLazyLoad()
{
$event = new Event();
$service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service');
$service
->expects($this->once())
->method('onEvent')
->with($event)
;
$container = new Container();
$container->set('service.listener', $service);
$dispatcher = new ContainerAwareEventDispatcher($container);
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
$this->assertTrue($dispatcher->hasListeners());
if ($dispatcher->hasListeners('onEvent')) {
$dispatcher->dispatch('onEvent');
}
}
public function testGetListenersOnLazyLoad()
{
$event = new Event();
$service = $this->getMock('Symfony\Bundle\FrameworkBundle\Tests\Service');
$container = new Container();
$container->set('service.listener', $service);
$dispatcher = new ContainerAwareEventDispatcher($container);
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
$listeners = $dispatcher->getListeners();
$this->assertTrue(isset($listeners['onEvent']));
$this->assertEquals(1, count($dispatcher->getListeners('onEvent')));
}
}
class Service

View File

@ -27,7 +27,7 @@
<service id="security.acl.provider" alias="security.acl.dbal.provider" />
<service id="security.acl.cache.doctrine" class="%security.acl.cache.doctrine.class%" public="false">
<argument type="service" id="security.acl.cache.doctrine_cache_impl" />
<argument type="service" id="security.acl.cache.doctrine.cache_impl" />
<argument type="service" id="security.acl.permission_granting_strategy" />
</service>

View File

@ -37,10 +37,13 @@ class RedirectResponse extends Response
}
parent::__construct(
sprintf('<html>
sprintf('<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="refresh" content="1;url=%1$s" />
<title>Redirecting to %1$s</title>
</head>
<body>
Redirecting to <a href="%1$s">%1$s</a>.

View File

@ -41,6 +41,7 @@ class SqliteProfilerStorage extends PdoProfilerStorage
throw new \RuntimeException('You need to enable either the SQLite3 or PDO_SQLite extension for the profiler to run properly.');
}
$db->exec('PRAGMA temp_store=MEMORY; PRAGMA journal_mode=MEMORY;');
$db->exec('CREATE TABLE IF NOT EXISTS sf_profiler_data (token STRING, data STRING, ip STRING, url STRING, time INTEGER, parent STRING, created_at INTEGER)');
$db->exec('CREATE INDEX IF NOT EXISTS data_created_at ON sf_profiler_data (created_at)');
$db->exec('CREATE INDEX IF NOT EXISTS data_ip ON sf_profiler_data (ip)');

View File

@ -33,14 +33,13 @@ class Filesystem
{
$this->mkdir(dirname($targetFile));
$mostRecent = false;
if (is_file($targetFile)) {
$statTarget = stat($targetFile);
$statOrigin = stat($originFile);
$mostRecent = $statOrigin['mtime'] > $statTarget['mtime'];
if (!$override && is_file($targetFile)) {
$doCopy = filemtime($originFile) > filemtime($targetFile);
} else {
$doCopy = true;
}
if ($override || !is_file($targetFile) || $mostRecent) {
if ($doCopy) {
copy($originFile, $targetFile);
}
}
@ -145,7 +144,7 @@ class Filesystem
*
* @param string $originDir The origin directory path
* @param string $targetDir The symbolic link name
* @param Boolean $copyOnWindows Whether to copy files if on windows
* @param Boolean $copyOnWindows Whether to copy files if on Windows
*/
public function symlink($originDir, $targetDir, $copyOnWindows = false)
{

View File

@ -105,6 +105,10 @@ abstract class AnnotationClassLoader implements LoaderInterface
);
$class = new \ReflectionClass($class);
if ($class->isAbstract()) {
throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class));
}
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
if (null !== $annot->getPattern()) {
$globals['pattern'] = $annot->getPattern();
@ -140,8 +144,9 @@ abstract class AnnotationClassLoader implements LoaderInterface
protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method)
{
if (null === $annot->getName()) {
$annot->setName($this->getDefaultRouteName($class, $method));
$name = $annot->getName();
if (null === $name) {
$name = $this->getDefaultRouteName($class, $method);
}
$defaults = array_merge($globals['defaults'], $annot->getDefaults());
@ -152,7 +157,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
$this->configureRoute($route, $class, $method, $annot);
$collection->add($annot->getName(), $route);
$collection->add($name, $route);
}
/**

View File

@ -44,6 +44,11 @@ class AnnotationDirectoryLoader extends AnnotationFileLoader
}
if ($class = $this->findClass($file)) {
$refl = new \ReflectionClass($class);
if ($refl->isAbstract()) {
continue;
}
$collection->addCollection($this->loader->load($class, $type));
}
}

View File

@ -92,7 +92,9 @@ class AnnotationFileLoader extends FileLoader
$class = false;
$namespace = false;
$tokens = token_get_all(file_get_contents($file));
while ($token = array_shift($tokens)) {
for ($i = 0, $count = count($tokens); $i < $count; $i++) {
$token = $tokens[$i];
if (!is_array($token)) {
continue;
}
@ -105,8 +107,8 @@ class AnnotationFileLoader extends FileLoader
$namespace = '';
do {
$namespace .= $token[1];
$token = array_shift($tokens);
} while ($tokens && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
$token = $tokens[++$i];
} while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
}
if (T_CLASS === $token[0]) {

View File

@ -80,13 +80,13 @@ class Interval
|
(?<left_delimiter>[\[\]])
(?P<left_delimiter>[\[\]])
\s*
(?<left>-Inf|\-?\d+)
(?P<left>-Inf|\-?\d+)
\s*,\s*
(?<right>\+?Inf|\-?\d+)
(?P<right>\+?Inf|\-?\d+)
\s*
(?<right_delimiter>[\[\]])
(?P<right_delimiter>[\[\]])
EOF;
}

View File

@ -54,7 +54,7 @@ class MessageSelector
foreach ($parts as $part) {
$part = trim($part);
if (preg_match('/^(?<interval>'.Interval::getIntervalRegexp().')\s+(?<message>.+?)$/x', $part, $matches)) {
if (preg_match('/^(?P<interval>'.Interval::getIntervalRegexp().')\s+(?P<message>.+?)$/x', $part, $matches)) {
$explicitRules[$matches['interval']] = $matches['message'];
} elseif (preg_match('/^\w+\: +(.+)$/', $part, $matches)) {
$standardRules[] = $matches[1];

View File

@ -31,7 +31,7 @@ class NotBlankValidator extends ConstraintValidator
*/
public function isValid($value, Constraint $constraint)
{
if (null === $value || '' === $value) {
if (false === $value || (empty($value) && '0' != $value)) {
$this->setMessage($constraint->message);
return false;

View File

@ -107,7 +107,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$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('This value is already used', $violation->getMessage());
$this->assertEquals('name', $violation->getPropertyPath());
$this->assertEquals('Foo', $violation->getInvalidValue());
}
@ -129,4 +129,25 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
$violationsList = $validator->validate($entity1);
$this->assertEquals(0, $violationsList->count(), "No violations found on entity having a null value.");
}
public function testValidateUniquenessAfterConsideringMultipleQueryResults()
{
$entityManagerName = "foo";
$em = $this->createTestEntityManager();
$this->createSchema($em);
$validator = $this->createValidator($entityManagerName, $em);
$entity1 = new SingleIdentEntity(1, 'foo');
$entity2 = new SingleIdentEntity(2, 'foo');
$em->persist($entity1);
$em->persist($entity2);
$em->flush();
$violationsList = $validator->validate($entity1);
$this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');
$violationsList = $validator->validate($entity2);
$this->assertEquals(1, $violationsList->count(), 'Violation found on entity with conflicting entity existing in the database.');
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Symfony\Tests\Component\Routing\Fixtures\AnnotatedClasses;
abstract class AbstractClass
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace Symfony\Tests\Component\Routing\Fixtures\AnnotatedClasses;
class FooClass
{
}

View File

@ -0,0 +1,36 @@
<?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\Tests\Component\Routing\Loader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
abstract class AbstractAnnotationLoaderTest extends \PHPUnit_Framework_TestCase
{
public function getReader()
{
return $this->getMockBuilder('Doctrine\Common\Annotations\Reader')
->disableOriginalConstructor()
->getMock()
;
}
public function getClassLoader($reader)
{
return $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader')
->setConstructorArgs(array($reader))
->getMockForAbstractClass()
;
}
}

View File

@ -16,20 +16,32 @@ use Symfony\Component\Routing\Loader\AnnotationClassLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class AnnotationClassLoaderTest extends \PHPUnit_Framework_TestCase
require_once __DIR__.'/../Fixtures/AnnotatedClasses/AbstractClass.php';
require_once __DIR__.'/AbstractAnnotationLoaderTest.php';
class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
{
protected $loader;
protected function setUp()
public function setUp()
{
$this->loader = $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader')
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->loader = $this->getClassLoader($this->getReader());
}
protected function tearDown()
/**
* @expectedException \InvalidArgumentException
*/
public function testLoadMissingClass()
{
$this->loader = null;
$this->loader->load('MissingClass');
}
/**
* @expectedException \InvalidArgumentException
*/
public function testLoadAbstractClass()
{
$this->loader->load('Symfony\Tests\Component\Routing\Fixtures\AnnotatedClasses\AbstractClass');
}
/**

View File

@ -17,25 +17,37 @@ use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\FileLocator;
class AnnotationDirectoryLoaderTest extends \PHPUnit_Framework_TestCase
require_once __DIR__.'/AbstractAnnotationLoaderTest.php';
class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest
{
protected $loader;
protected $reader;
public function setUp()
{
$this->reader = $this->getReader();
$this->loader = new AnnotationDirectoryLoader(new FileLocator(), $this->getClassLoader($this->reader));
}
public function testLoad()
{
$this->reader->expects($this->once())->method('getClassAnnotation');
$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses');
}
/**
* @covers Symfony\Component\Routing\Loader\AnnotationDirectoryLoader::supports
*/
public function testSupports()
{
$annotationClassLoader = $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader')
->disableOriginalConstructor()
->getMockForAbstractClass();
$loader = new AnnotationDirectoryLoader(new FileLocator(), $annotationClassLoader);
$fixturesDir = __DIR__.'/../Fixtures';
$this->assertTrue($loader->supports($fixturesDir), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
$this->assertTrue($this->loader->supports($fixturesDir), '->supports() returns true if the resource is loadable');
$this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
$this->assertTrue($loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified');
$this->assertFalse($loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified');
$this->assertTrue($this->loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified');
$this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified');
}
}

View File

@ -15,26 +15,39 @@ use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Config\FileLocator;
class AnnotationFileLoaderTest extends \PHPUnit_Framework_TestCase
require_once __DIR__.'/AbstractAnnotationLoaderTest.php';
class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
{
protected $loader;
protected $reader;
public function setUp()
{
$this->reader = $this->getReader();
$this->loader = new AnnotationFileLoader(new FileLocator(), $this->getClassLoader($this->reader));
}
public function testLoad()
{
$this->reader->expects($this->once())->method('getClassAnnotation');
$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php');
}
/**
* @covers Symfony\Component\Routing\Loader\AnnotationFileLoader::supports
*/
public function testSupports()
{
$annotationClassLoader = $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader')
->disableOriginalConstructor()
->getMockForAbstractClass();
$loader = new AnnotationFileLoader($this->getMock('Symfony\Component\Config\FileLocator'), $annotationClassLoader);
$fixture = __DIR__.'/../Fixtures/annotated.php';
$this->assertTrue($loader->supports($fixture), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
$this->assertTrue($this->loader->supports($fixture), '->supports() returns true if the resource is loadable');
$this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
$this->assertTrue($loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified');
$this->assertFalse($loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified');
$this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified');
$this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified');
}
}

View File

@ -29,19 +29,20 @@ class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase
}
/**
* @dataProvider getInvalidValues
* @dataProvider getValidValues
*/
public function testInvalidValues($date)
public function testValidValues($date)
{
$this->assertTrue($this->validator->isValid($date, new NotBlank()));
}
public function getInvalidValues()
public function getValidValues()
{
return array(
array('foobar'),
array(0),
array(false),
array(0.0),
array('0'),
array(1234),
);
}
@ -56,6 +57,16 @@ class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($this->validator->isValid('', new NotBlank()));
}
public function testFalseIsInvalid()
{
$this->assertFalse($this->validator->isValid(false, new NotBlank()));
}
public function testEmptyArrayIsInvalid()
{
$this->assertFalse($this->validator->isValid(array(), new NotBlank()));
}
public function testSetMessage()
{
$constraint = new NotBlank(array(
@ -67,3 +78,4 @@ class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($this->validator->getMessageParameters(), array());
}
}