From 0423d894f43a60da6d1625906f1fea536dcb5513 Mon Sep 17 00:00:00 2001 From: VJ Date: Tue, 1 Nov 2016 13:31:37 -0400 Subject: [PATCH 01/10] [HttpFoundation][Session] memcached connection should not be closed --- .../Session/Storage/Handler/MemcacheSessionHandler.php | 2 +- .../Session/Storage/Handler/MemcacheSessionHandlerTest.php | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index a386bdd184..962a3878d9 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -71,7 +71,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface */ public function close() { - return $this->memcache->close(); + return true; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php index 0c579d7724..6745a22455 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -56,12 +56,6 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase public function testCloseSession() { - $this->memcache - ->expects($this->once()) - ->method('close') - ->will($this->returnValue(true)) - ; - $this->assertTrue($this->storage->close()); } From e64de1eac65779f1aa3c9c9c4203ea2e64558907 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 1 Nov 2016 20:56:21 +0100 Subject: [PATCH 02/10] =?UTF-8?q?[Console]=C2=A0Fix=20infinite=20loop=20on?= =?UTF-8?q?=20missing=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Console] Use console exception for missing input Backport Console RuntimeException in 2.7 --- .../Console/Exception/RuntimeException.php | 19 ++++++++++++ .../Console/Helper/QuestionHelper.php | 9 ++++-- .../Tests/Helper/QuestionHelperTest.php | 31 +++++++++++++++++++ .../Helper/SymfonyQuestionHelperTest.php | 12 +++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Console/Exception/RuntimeException.php diff --git a/src/Symfony/Component/Console/Exception/RuntimeException.php b/src/Symfony/Component/Console/Exception/RuntimeException.php new file mode 100644 index 0000000000..1324558a7b --- /dev/null +++ b/src/Symfony/Component/Console/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class RuntimeException extends \RuntimeException +{ +} diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 6d6850d1ae..90055b8a70 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Exception\RuntimeException; /** * The QuestionHelper class provides helpers to interact with the user. @@ -134,7 +135,7 @@ class QuestionHelper extends Helper if (false === $ret) { $ret = fgets($inputStream, 4096); if (false === $ret) { - throw new \RuntimeException('Aborted'); + throw new RuntimeException('Aborted'); } $ret = trim($ret); } @@ -354,7 +355,7 @@ class QuestionHelper extends Helper shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { - throw new \RuntimeException('Aborted'); + throw new RuntimeException('Aborted'); } $value = trim($value); @@ -372,7 +373,7 @@ class QuestionHelper extends Helper return $value; } - throw new \RuntimeException('Unable to hide the response.'); + throw new RuntimeException('Unable to hide the response.'); } /** @@ -397,6 +398,8 @@ class QuestionHelper extends Helper try { return call_user_func($question->getValidator(), $interviewer()); + } catch (RuntimeException $e) { + throw $e; } catch (\Exception $error) { } } diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 6a4f8aceae..86ad446c1b 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -402,6 +402,37 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $dialog->ask($this->createInputInterfaceMock(), $output, $question); } + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInput() + { + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream('')); + + $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), new Question('What\'s your name?')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInputWithValidator() + { + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream('')); + + $question = new Question('What\'s your name?'); + $question->setValidator(function () { + if (!$value) { + throw new \Exception('A value is required.'); + } + }); + + $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + } + protected function getInputStream($input) { $stream = fopen('php://memory', 'r+', false); diff --git a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php index 91f51245ac..f57d65070e 100644 --- a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php @@ -101,6 +101,18 @@ class SymfonyQuestionHelperTest extends \PHPUnit_Framework_TestCase $this->assertOutputContains('Do you want a \?', $output); } + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInput() + { + $dialog = new SymfonyQuestionHelper(); + + $dialog->setInputStream($this->getInputStream('')); + $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), new Question('What\'s your name?')); + } + protected function getInputStream($input) { $stream = fopen('php://memory', 'r+', false); From ad54d83c902a80367d27d946b00b6f3808e1e26b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 4 Nov 2016 11:57:19 +0100 Subject: [PATCH 03/10] [Yaml] set arguments depending on the PHP version --- src/Symfony/Component/Yaml/Tests/InlineTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index e414abd38b..83d20cc96c 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -507,7 +507,12 @@ class InlineTest extends \PHPUnit_Framework_TestCase $expected = new \DateTime($yaml); $expected->setTimeZone(new \DateTimeZone('UTC')); $expected->setDate($year, $month, $day); - @$expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); + + if (PHP_VERSION_ID >= 70100) { + $expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); + } else { + $expected->setTime($hour, $minute, $second); + } $this->assertEquals($expected, Inline::parse($yaml, Yaml::PARSE_DATETIME)); } From d030a9d4036894a2a77af2100e3d23e597a0b65c Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 25 Oct 2016 11:20:09 +0200 Subject: [PATCH 04/10] Improved the design of the metrics in the profiler --- .../Resources/views/Collector/time.html.twig | 20 ++++++++++--------- .../views/Profiler/profiler.css.twig | 10 ++++++++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index 98ea6c3265..6860230243 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -60,10 +60,19 @@ Symfony initialization + {% if profile.collectors.memory %} +
+ {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MB + Peak memory usage +
+ {% endif %} + {% if profile.children|length > 0 %} +
+
{{ profile.children|length }} - Sub-Requests + Sub-Request{{ profile.children|length > 1 ? 's' }}
{% set subrequests_time = 0 %} @@ -73,14 +82,7 @@
{{ subrequests_time }} ms - Sub-Requests time -
- {% endif %} - - {% if profile.collectors.memory %} -
- {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MB - Peak memory usage + Sub-Request{{ profile.children|length > 1 ? 's' }} time
{% endif %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 4d458d3242..b807d0bcf9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -250,12 +250,12 @@ table tbody ul { {# Metrics ------------------------------------------------------------------------- #} .metrics { - margin: 1em 0; + margin: 1em 0 0; overflow: auto; } .metrics .metric { float: left; - margin-right: 1em; + margin: 0 1em 1em 0; } .metric { @@ -310,6 +310,12 @@ table tbody ul { vertical-align: middle; } +.metric-divider { + float: left; + margin: 0 1em; + min-height: 1px; {# required to apply 'margin' to an empty 'div' #} +} + {# Cards ------------------------------------------------------------------------- #} .card { From c3dacbb9a1418e3e7c433152439f7e6ae390706f Mon Sep 17 00:00:00 2001 From: Jan Emrich Date: Fri, 4 Nov 2016 18:49:05 +0100 Subject: [PATCH 05/10] Remove double use Statement Syntax Error in Helper/QuestionHelper.php --- src/Symfony/Component/Console/Helper/QuestionHelper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 5244bb5fb8..4b4e1a63f9 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Exception\RuntimeException; /** * The QuestionHelper class provides helpers to interact with the user. From 35642288faebec8b5d8ec9028494b43b78348a69 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Tue, 1 Nov 2016 16:33:50 -0400 Subject: [PATCH 06/10] [Form] Fix show float values as choices values in ChoiceType --- .../Component/Form/ChoiceList/ArrayChoiceList.php | 6 +++++- .../Form/Tests/ChoiceList/ArrayChoiceListTest.php | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index 7f2824fab2..4a2588ef1d 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -236,7 +236,11 @@ class ArrayChoiceList implements ChoiceListInterface continue; } elseif (!is_scalar($choice)) { return false; - } elseif (isset($cache[$choice])) { + } + + $choice = false === $choice ? '0' : (string) $choice; + + if (isset($cache[$choice])) { return false; } diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php index 09bcc9c4c2..3b041eab29 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php @@ -34,12 +34,12 @@ class ArrayChoiceListTest extends AbstractChoiceListTest protected function getChoices() { - return array(0, 1, '1', 'a', false, true, $this->object, null); + return array(0, 1, 1.5, '1', 'a', false, true, $this->object, null); } protected function getValues() { - return array('0', '1', '2', '3', '4', '5', '6', '7'); + return array('0', '1', '2', '3', '4', '5', '6', '7', '8'); } /** @@ -162,4 +162,13 @@ class ArrayChoiceListTest extends AbstractChoiceListTest $this->assertSame(array(0 => true), $choiceList->getChoicesForValues(array('1'))); $this->assertSame(array(0 => false), $choiceList->getChoicesForValues(array('0'))); } + + public function testGetChoicesForValuesWithContainingEmptyStringAndFloats() + { + $choiceList = new ArrayChoiceList(array('Empty String' => '', '1/3' => 0.3, '1/2' => 0.5)); + + $this->assertSame(array(0 => ''), $choiceList->getChoicesForValues(array(''))); + $this->assertSame(array(0 => 0.3), $choiceList->getChoicesForValues(array('0.3'))); + $this->assertSame(array(0 => 0.5), $choiceList->getChoicesForValues(array('0.5'))); + } } From eb0d6c94ca51aef6701dff88fbea2e8616e0e72d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 5 Nov 2016 23:09:07 -0700 Subject: [PATCH 07/10] removed a deprecation notice --- .../NodeVisitor/TranslationDefaultDomainNodeVisitor.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index b226d91adf..e64d6eae23 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -49,7 +49,7 @@ class TranslationDefaultDomainNodeVisitor extends \Twig_BaseNodeVisitor return $node; } else { - $var = $env->getParser()->getVarName(); + $var = $this->getVarName(); $name = new \Twig_Node_Expression_AssignName($var, $node->getTemplateLine()); $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getTemplateLine())); @@ -123,4 +123,9 @@ class TranslationDefaultDomainNodeVisitor extends \Twig_BaseNodeVisitor return false; } + + private function getVarName() + { + return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); + } } From 27c91e514e563e090d9f8122235cf61951cde5bd Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Sun, 6 Nov 2016 08:05:17 +0000 Subject: [PATCH 08/10] [Translation][fallback] add missing resources in parent catalogues. --- .../Component/Translation/MessageCatalogue.php | 4 ++++ .../Translation/Tests/MessageCatalogueTest.php | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Translation/MessageCatalogue.php b/src/Symfony/Component/Translation/MessageCatalogue.php index dd354a85aa..73649fb6dd 100644 --- a/src/Symfony/Component/Translation/MessageCatalogue.php +++ b/src/Symfony/Component/Translation/MessageCatalogue.php @@ -178,6 +178,10 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf if ($c->getLocale() === $catalogue->getLocale()) { throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); } + + foreach ($catalogue->getResources() as $resource) { + $c->addResource($resource); + } } while ($c = $c->parent); $catalogue->parent = $this; diff --git a/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php b/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php index 6f55b8cc5e..e5bb981004 100644 --- a/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php +++ b/src/Symfony/Component/Translation/Tests/MessageCatalogueTest.php @@ -110,18 +110,25 @@ class MessageCatalogueTest extends \PHPUnit_Framework_TestCase $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface'); $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1')); - $catalogue = new MessageCatalogue('en_US', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar'))); + $r2 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface'); + $r2->expects($this->any())->method('__toString')->will($this->returnValue('r2')); + + $catalogue = new MessageCatalogue('fr_FR', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar'))); $catalogue->addResource($r); - $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1'))); + $catalogue1 = new MessageCatalogue('fr', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1'))); $catalogue1->addResource($r1); + $catalogue2 = new MessageCatalogue('en'); + $catalogue2->addResource($r2); + $catalogue->addFallbackCatalogue($catalogue1); + $catalogue1->addFallbackCatalogue($catalogue2); $this->assertEquals('foo', $catalogue->get('foo', 'domain1')); $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); - $this->assertEquals(array($r, $r1), $catalogue->getResources()); + $this->assertEquals(array($r, $r1, $r2), $catalogue->getResources()); } /** From 9043a551b2f2ebacc00564a249234f2d32df7469 Mon Sep 17 00:00:00 2001 From: Andreas Braun Date: Mon, 24 Oct 2016 11:16:47 +0200 Subject: [PATCH 09/10] Properly format value in UniqueEntityValidator --- .../Doctrine/Test/DoctrineTestHelper.php | 34 ++++++-- .../Doctrine/Test/TestRepositoryFactory.php | 85 +++++++++++++++++++ .../Tests/Fixtures/SingleIntIdEntity.php | 3 + .../Constraints/UniqueEntityValidatorTest.php | 58 +++++++++++-- .../Constraints/UniqueEntityValidator.php | 2 +- 5 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php diff --git a/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php b/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php index 962099e36a..e7f4555d07 100644 --- a/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php +++ b/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php @@ -12,6 +12,8 @@ namespace Symfony\Bridge\Doctrine\Test; use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\ORM\Configuration; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\EntityManager; @@ -25,22 +27,19 @@ class DoctrineTestHelper /** * Returns an entity manager for testing. * + * @param Configuration|null $config + * * @return EntityManager */ - public static function createTestEntityManager() + public static function createTestEntityManager(Configuration $config = null) { if (!extension_loaded('pdo_sqlite')) { \PHPUnit_Framework_TestCase::markTestSkipped('Extension pdo_sqlite is required.'); } - $config = new \Doctrine\ORM\Configuration(); - $config->setEntityNamespaces(array('SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures')); - $config->setAutoGenerateProxyClasses(true); - $config->setProxyDir(\sys_get_temp_dir()); - $config->setProxyNamespace('SymfonyTests\Doctrine'); - $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); - $config->setQueryCacheImpl(new \Doctrine\Common\Cache\ArrayCache()); - $config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache()); + if (null === $config) { + $config = self::createTestConfiguration(); + } $params = array( 'driver' => 'pdo_sqlite', @@ -50,6 +49,23 @@ class DoctrineTestHelper return EntityManager::create($params, $config); } + /** + * @return Configuration + */ + public static function createTestConfiguration() + { + $config = new Configuration(); + $config->setEntityNamespaces(array('SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures')); + $config->setAutoGenerateProxyClasses(true); + $config->setProxyDir(\sys_get_temp_dir()); + $config->setProxyNamespace('SymfonyTests\Doctrine'); + $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); + $config->setQueryCacheImpl(new ArrayCache()); + $config->setMetadataCacheImpl(new ArrayCache()); + + return $config; + } + /** * This class cannot be instantiated. */ diff --git a/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php b/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php new file mode 100644 index 0000000000..b94a095f35 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Test; + +use Doctrine\Common\Persistence\ObjectRepository; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Repository\RepositoryFactory; + +/** + * @author Andreas Braun + */ +final class TestRepositoryFactory implements RepositoryFactory +{ + /** + * The list of EntityRepository instances. + * + * @var ObjectRepository[] + */ + private $repositoryList = array(); + + /** + * {@inheritdoc} + */ + public function getRepository(EntityManagerInterface $entityManager, $entityName) + { + $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); + + if (isset($this->repositoryList[$repositoryHash])) { + return $this->repositoryList[$repositoryHash]; + } + + return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); + } + + /** + * @param EntityManagerInterface $entityManager + * @param string $entityName + * @param ObjectRepository $repository + */ + public function setRepository(EntityManagerInterface $entityManager, $entityName, ObjectRepository $repository) + { + $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); + + $this->repositoryList[$repositoryHash] = $repository; + } + + /** + * Create a new repository instance for an entity class. + * + * @param EntityManagerInterface $entityManager The EntityManager instance. + * @param string $entityName The name of the entity. + * + * @return ObjectRepository + */ + private function createRepository(EntityManagerInterface $entityManager, $entityName) + { + /* @var $metadata ClassMetadata */ + $metadata = $entityManager->getClassMetadata($entityName); + $repositoryClassName = $metadata->customRepositoryClassName + ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); + + return new $repositoryClassName($entityManager, $metadata); + } + + /** + * @param EntityManagerInterface $entityManager + * @param string $entityName + * + * @return string + */ + private function getRepositoryHash(EntityManagerInterface $entityManager, $entityName) + { + return $entityManager->getClassMetadata($entityName)->getName().spl_object_hash($entityManager); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php index 44630a1fc5..6ee360e6a1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdEntity.php @@ -24,6 +24,9 @@ class SingleIntIdEntity /** @Column(type="string", nullable=true) */ public $name; + /** @Column(type="array", nullable=true) */ + public $phoneNumbers = array(); + public function __construct($id, $name) { $this->id = $id; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 7299f106b8..2e2f2952e0 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -16,6 +16,7 @@ use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectRepository; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; +use Symfony\Bridge\Doctrine\Test\TestRepositoryFactory; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNameEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity; @@ -48,9 +49,16 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest */ protected $repository; + protected $repositoryFactory; + protected function setUp() { - $this->em = DoctrineTestHelper::createTestEntityManager(); + $this->repositoryFactory = new TestRepositoryFactory(); + + $config = DoctrineTestHelper::createTestConfiguration(); + $config->setRepositoryFactory($this->repositoryFactory); + + $this->em = DoctrineTestHelper::createTestEntityManager($config); $this->registry = $this->createRegistryMock($this->em); $this->createSchema($this->em); @@ -164,7 +172,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->buildViolation('myMessage') ->atPath('property.path.name') - ->setParameter('{{ value }}', 'Foo') + ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue('Foo') ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); @@ -189,7 +197,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->buildViolation('myMessage') ->atPath('property.path.bar') - ->setParameter('{{ value }}', 'Foo') + ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue('Foo') ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); @@ -242,7 +250,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->buildViolation('myMessage') ->atPath('property.path.name') - ->setParameter('{{ value }}', 'Foo') + ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue('Foo') ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); @@ -275,7 +283,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->buildViolation('myMessage') ->atPath('property.path.name2') - ->setParameter('{{ value }}', 'Bar') + ->setParameter('{{ value }}', '"Bar"') ->setInvalidValue('Bar') ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); @@ -446,7 +454,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->buildViolation('myMessage') ->atPath('property.path.single') - ->setParameter('{{ value }}', $expectedValue) + ->setParameter('{{ value }}', '"'.$expectedValue.'"') ->setInvalidValue($expectedValue) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); @@ -472,6 +480,44 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $this->assertNoViolation(); } + public function testValidateUniquenessWithArrayValue() + { + $repository = $this->createRepositoryMock(); + $this->repositoryFactory->setRepository($this->em, 'Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', $repository); + + $constraint = new UniqueEntity(array( + 'message' => 'myMessage', + 'fields' => array('phoneNumbers'), + 'em' => self::EM_NAME, + 'repositoryMethod' => 'findByCustom', + )); + + $entity1 = new SingleIntIdEntity(1, 'foo'); + $entity1->phoneNumbers[] = 123; + + $repository->expects($this->once()) + ->method('findByCustom') + ->will($this->returnValue(array($entity1))) + ; + + $this->em->persist($entity1); + $this->em->flush(); + + $entity2 = new SingleIntIdEntity(2, 'bar'); + $entity2->phoneNumbers[] = 123; + $this->em->persist($entity2); + $this->em->flush(); + + $this->validator->validate($entity2, $constraint); + + $this->buildViolation('myMessage') + ->atPath('property.path.phoneNumbers') + ->setParameter('{{ value }}', 'array') + ->setInvalidValue(array(123)) + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->assertRaised(); + } + /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException * @expectedExceptionMessage Object manager "foo" does not exist. diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 4fd8afff17..eb90b78af2 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -133,7 +133,7 @@ class UniqueEntityValidator extends ConstraintValidator $this->context->buildViolation($constraint->message) ->atPath($errorPath) - ->setParameter('{{ value }}', $invalidValue) + ->setParameter('{{ value }}', $this->formatValue($invalidValue, static::OBJECT_TO_STRING | static::PRETTY_DATE)) ->setInvalidValue($invalidValue) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->addViolation(); From ba8a12a89867e127829b774744aa95ad3fb64fdd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 6 Nov 2016 08:20:57 -0800 Subject: [PATCH 10/10] fixed CS --- .../Doctrine/Test/TestRepositoryFactory.php | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php b/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php index b94a095f35..b7cbafa947 100644 --- a/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php +++ b/src/Symfony/Bridge/Doctrine/Test/TestRepositoryFactory.php @@ -22,8 +22,6 @@ use Doctrine\ORM\Repository\RepositoryFactory; final class TestRepositoryFactory implements RepositoryFactory { /** - * The list of EntityRepository instances. - * * @var ObjectRepository[] */ private $repositoryList = array(); @@ -42,11 +40,6 @@ final class TestRepositoryFactory implements RepositoryFactory return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); } - /** - * @param EntityManagerInterface $entityManager - * @param string $entityName - * @param ObjectRepository $repository - */ public function setRepository(EntityManagerInterface $entityManager, $entityName, ObjectRepository $repository) { $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); @@ -55,29 +48,17 @@ final class TestRepositoryFactory implements RepositoryFactory } /** - * Create a new repository instance for an entity class. - * - * @param EntityManagerInterface $entityManager The EntityManager instance. - * @param string $entityName The name of the entity. - * * @return ObjectRepository */ private function createRepository(EntityManagerInterface $entityManager, $entityName) { /* @var $metadata ClassMetadata */ $metadata = $entityManager->getClassMetadata($entityName); - $repositoryClassName = $metadata->customRepositoryClassName - ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); + $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); return new $repositoryClassName($entityManager, $metadata); } - /** - * @param EntityManagerInterface $entityManager - * @param string $entityName - * - * @return string - */ private function getRepositoryHash(EntityManagerInterface $entityManager, $entityName) { return $entityManager->getClassMetadata($entityName)->getName().spl_object_hash($entityManager);