From 041c42db6a1247007eb1ef412a54357a2a21522f Mon Sep 17 00:00:00 2001 From: Mathieu Lechat Date: Wed, 10 Jan 2018 13:22:09 +0100 Subject: [PATCH 01/68] Allow trans filter to be safe --- .../Twig/Resources/views/Form/form_div_layout.html.twig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 7df55bc4d3879..a5b72c17622c1 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -219,7 +219,13 @@ {% set label = name|humanize %} {%- endif -%} {%- endif -%} - {{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }} + + {%- if translation_domain is same as(false) -%} + {{- label -}} + {%- else -%} + {{- label|trans({}, translation_domain) -}} + {%- endif -%} + {%- endif -%} {%- endblock form_label -%} From 317da3bdf83c5834dde2fc850509d39da8435472 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Jan 2018 17:21:59 +0100 Subject: [PATCH 02/68] keep the context when validating forms --- .../Form/Extension/Validator/Constraints/FormValidator.php | 2 ++ .../Tests/Extension/Validator/Constraints/FormValidatorTest.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index bddb8a09e8603..4183e1a726593 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -124,6 +124,7 @@ public function validate($form, Constraint $constraint) : gettype($form->getViewData()); if ($this->context instanceof ExecutionContextInterface) { + $this->context->setConstraint($constraint); $this->context->buildViolation($config->getOption('invalid_message')) ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) ->setInvalidValue($form->getViewData()) @@ -144,6 +145,7 @@ public function validate($form, Constraint $constraint) // Mark the form with an error if it contains extra fields if (!$config->getOption('allow_extra_fields') && count($form->getExtraData()) > 0) { if ($this->context instanceof ExecutionContextInterface) { + $this->context->setConstraint($constraint); $this->context->buildViolation($config->getOption('extra_fields_message')) ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) ->setInvalidValue($form->getExtraData()) diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 78015b504940b..4bb360a99fe0a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -51,6 +51,8 @@ protected function setUp() $this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Extension\Validator\Util\ServerParams')->setMethods(array('getNormalizedIniPostMaxSize', 'getContentLength'))->getMock(); parent::setUp(); + + $this->constraint = new Form(); } protected function getApiVersion() From 9722c063fb18e850d591711fd7113369aafcf272 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Thu, 25 Jan 2018 23:08:02 +0100 Subject: [PATCH 03/68] [Form] Fixed empty data on expanded ChoiceType and FileType --- .../Form/Extension/Core/Type/ChoiceType.php | 9 +- .../Form/Extension/Core/Type/FileType.php | 15 ++-- .../Extension/Core/Type/ChoiceTypeTest.php | 90 +++++++++++++++++++ 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 46a57190cf5a5..601583b7839f8 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -33,7 +33,6 @@ use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; -use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -91,12 +90,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) $form = $event->getForm(); $data = $event->getData(); + // Since the type always use mapper an empty array will not be + // considered as empty in Form::submit(), we need to evaluate + // empty data here so its value is submitted to sub forms if (null === $data) { $emptyData = $form->getConfig()->getEmptyData(); - - if (false === FormUtil::isEmpty($emptyData) && array() !== $emptyData) { - $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData; - } + $data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData; } // Convert the submitted data to a string, if scalar, before diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index 7d84512d9b3c7..321cbc03690e5 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -27,10 +27,10 @@ class FileType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { + // Ensure that submitted data is always an uploaded file or an array of some $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) { $form = $event->getForm(); $requestHandler = $form->getConfig()->getRequestHandler(); - $data = null; if ($options['multiple']) { $data = array(); @@ -46,19 +46,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) } } - // submitted data for an input file (not required) without choosing any file - if (array(null) === $data || array() === $data) { + // Since the array is never considered empty in the view data format + // on submission, we need to evaluate the configured empty data here + if (array() === $data) { $emptyData = $form->getConfig()->getEmptyData(); - - $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData; + $data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData; } $event->setData($data); } elseif (!$requestHandler->isFileUpload($event->getData())) { - $emptyData = $form->getConfig()->getEmptyData(); - - $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData; - $event->setData($data); + $event->setData(null); } }); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 9b0983eac5937..842136e14c677 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -690,6 +690,21 @@ public function testSubmitSingleChoiceWithEmptyData() $this->assertSame('test', $form->getData()); } + public function testSubmitSingleChoiceWithEmptyDataAndInitialData() + { + $form = $this->factory->create(static::TESTED_TYPE, 'initial', array( + 'multiple' => false, + 'expanded' => false, + 'choices' => array('initial', 'test'), + 'choices_as_values' => true, + 'empty_data' => 'test', + )); + + $form->submit(null); + + $this->assertSame('test', $form->getData()); + } + public function testSubmitMultipleChoiceWithEmptyData() { $form = $this->factory->create(static::TESTED_TYPE, null, array( @@ -705,6 +720,36 @@ public function testSubmitMultipleChoiceWithEmptyData() $this->assertSame(array('test'), $form->getData()); } + public function testSubmitMultipleChoiceWithEmptyDataAndInitialEmptyArray() + { + $form = $this->factory->create(static::TESTED_TYPE, array(), array( + 'multiple' => true, + 'expanded' => false, + 'choices' => array('test'), + 'choices_as_values' => true, + 'empty_data' => array('test'), + )); + + $form->submit(null); + + $this->assertSame(array('test'), $form->getData()); + } + + public function testSubmitMultipleChoiceWithEmptyDataAndInitialData() + { + $form = $this->factory->create(static::TESTED_TYPE, array('initial'), array( + 'multiple' => true, + 'expanded' => false, + 'choices' => array('initial', 'test'), + 'choices_as_values' => true, + 'empty_data' => array('test'), + )); + + $form->submit(null); + + $this->assertSame(array('test'), $form->getData()); + } + public function testSubmitSingleChoiceExpandedWithEmptyData() { $form = $this->factory->create(static::TESTED_TYPE, null, array( @@ -720,6 +765,21 @@ public function testSubmitSingleChoiceExpandedWithEmptyData() $this->assertSame('test', $form->getData()); } + public function testSubmitSingleChoiceExpandedWithEmptyDataAndInitialData() + { + $form = $this->factory->create(static::TESTED_TYPE, 'initial', array( + 'multiple' => false, + 'expanded' => true, + 'choices' => array('initial', 'test'), + 'choices_as_values' => true, + 'empty_data' => 'test', + )); + + $form->submit(null); + + $this->assertSame('test', $form->getData()); + } + public function testSubmitMultipleChoiceExpandedWithEmptyData() { $form = $this->factory->create(static::TESTED_TYPE, null, array( @@ -735,6 +795,36 @@ public function testSubmitMultipleChoiceExpandedWithEmptyData() $this->assertSame(array('test'), $form->getData()); } + public function testSubmitMultipleChoiceExpandedWithEmptyDataAndInitialEmptyArray() + { + $form = $this->factory->create(static::TESTED_TYPE, array(), array( + 'multiple' => true, + 'expanded' => true, + 'choices' => array('test'), + 'choices_as_values' => true, + 'empty_data' => array('test'), + )); + + $form->submit(null); + + $this->assertSame(array('test'), $form->getData()); + } + + public function testSubmitMultipleChoiceExpandedWithEmptyDataAndInitialData() + { + $form = $this->factory->create(static::TESTED_TYPE, array('init'), array( + 'multiple' => true, + 'expanded' => true, + 'choices' => array('init', 'test'), + 'choices_as_values' => true, + 'empty_data' => array('test'), + )); + + $form->submit(null); + + $this->assertSame(array('test'), $form->getData()); + } + /** * @group legacy */ From b18f9e76a5b32a853d9ca183913cf58c4b41959e Mon Sep 17 00:00:00 2001 From: Dariusz Date: Sun, 21 Jan 2018 19:35:11 +0100 Subject: [PATCH 04/68] [HttpFoundation] Added "null" type on Request::create docblock --- .../Component/HttpFoundation/Request.php | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 297f036a2f099..fe7080ab86321 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -130,7 +130,7 @@ class Request public $headers; /** - * @var string|resource + * @var string|resource|false|null */ protected $content; @@ -207,13 +207,13 @@ class Request protected static $requestFactory; /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource $content The raw body data + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data */ public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { @@ -225,13 +225,13 @@ public function __construct(array $query = array(), array $request = array(), ar * * This method also re-initializes all properties. * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource $content The raw body data + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data */ public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { @@ -294,13 +294,13 @@ public static function createFromGlobals() * The information contained in the URI always take precedence * over the other information (server and parameters). * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource $content The raw body data + * @param string $uri The URI + * @param string $method The HTTP method + * @param array $parameters The query (GET) or request (POST) parameters + * @param array $cookies The request cookies ($_COOKIE) + * @param array $files The request files ($_FILES) + * @param array $server The server parameters ($_SERVER) + * @param string|resource|null $content The raw body data * * @return static */ From 6d59c13e7184cead29f8c2c6010154e902a8541e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Jan 2018 11:08:21 +0100 Subject: [PATCH 05/68] updated CHANGELOG for 2.7.41 --- CHANGELOG-2.7.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 16c5342500901..3b9be1a043a02 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,34 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.41 (2018-01-29) + + * bug #25922 [HttpFoundation] Use the correct syntax for session gc based on Pdo driver (tanasecosminromeo) + * bug #25933 Disable CSP header on exception pages only in debug (ostrolucky) + * bug #25926 [Form] Fixed Button::setParent() when already submitted (HeahDude) + * bug #25927 [Form] Fixed submitting disabled buttons (HeahDude) + * bug #25891 [DependencyInjection] allow null values for root nodes in YAML configs (xabbuh) + * bug #25848 [Validator] add missing parent isset and add test (Simperfit) + * bug #25861 do not conflict with egulias/email-validator 2.0+ (xabbuh) + * bug #25851 [Validator] Conflict with egulias/email-validator 2.0 (emodric) + * bug #25837 [SecurityBundle] Don't register in memory users as services (chalasr) + * bug #25835 [HttpKernel] DebugHandlersListener should always replace the existing exception handler (nicolas-grekas) + * bug #25829 [Debug] Always decorate existing exception handlers to deal with fatal errors (nicolas-grekas) + * bug #25824 Fixing a bug where the dump() function depended on bundle ordering (weaverryan) + * bug #25789 Enableable ArrayNodeDefinition is disabled for empty configuration (kejwmen) + * bug #25816 Problem in phar see mergerequest #25579 (betzholz) + * bug #25781 [Form] Disallow transform dates beyond the year 9999 (curry684) + * bug #25812 Copied NO language files to the new NB locale (derrabus) + * bug #25801 [Router] Skip anonymous classes when loading annotated routes (pierredup) + * bug #25657 [Security] Fix fatal error on non string username (chalasr) + * bug #25799 Fixed Request::__toString ignoring cookies (Toflar) + * bug #25755 [Debug] prevent infinite loop with faulty exception handlers (nicolas-grekas) + * bug #25771 [Validator] 19 digits VISA card numbers are valid (xabbuh) + * bug #25751 [FrameworkBundle] Add the missing `enabled` session attribute (sroze) + * bug #25750 [HttpKernel] Turn bad hosts into 400 instead of 500 (nicolas-grekas) + * bug #25490 [Serializer] Fixed throwing exception with option JSON_PARTIAL_OUTPUT_ON_ERROR (diversantvlz) + * feature #25669 [Security] Fail gracefully if the security token cannot be unserialized from the session (thewilkybarkid) + * 2.7.40 (2018-01-05) * bug #25532 [HttpKernel] Disable CSP header on exception pages (ostrolucky) From 50931d83f50a0069479a802b2e3b9b6f6b088f39 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Jan 2018 11:08:31 +0100 Subject: [PATCH 06/68] update CONTRIBUTORS for 2.7.41 --- CONTRIBUTORS.md | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 85b3003b2abc6..96a8a8f23cc19 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -16,8 +16,8 @@ Symfony is the result of the work of many people who made the code better - Kévin Dunglas (dunglas) - Jakub Zalas (jakubzalas) - Kris Wallsmith (kriswallsmith) - - Ryan Weaver (weaverryan) - Robin Chalas (chalas_r) + - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) - Maxime Steinhausser (ogizanagi) - Hugo Hamon (hhamon) @@ -58,21 +58,21 @@ Symfony is the result of the work of many people who made the code better - Diego Saint Esteben (dii3g0) - Dany Maillard (maidmaid) - Konstantin Kudryashov (everzet) + - Amrouche Hamza (simperfit) - Kevin Bond (kbond) - - Bilal Amarni (bamarni) - Pierre du Plessis (pierredup) + - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - Jérémy DERUSSÉ (jderusse) - - Amrouche Hamza (simperfit) + - Samuel ROZE (sroze) - Gábor Egyed (1ed) + - Alexander M. Turek (derrabus) - Michel Weimerskirch (mweimerskirch) - Andrej Hudec (pulzarraider) - - Alexander M. Turek (derrabus) - Eric Clemmons (ericclemmons) - Jáchym Toušek (enumag) - Charles Sarrazin (csarrazi) - Titouan Galopin (tgalopin) - - Samuel ROZE (sroze) - Konstantin Myakshin (koc) - Christian Raue - Arnout Boks (aboks) @@ -100,9 +100,9 @@ Symfony is the result of the work of many people who made the code better - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - David Maicher (dmaicher) - Vladimir Reznichenko (kalessil) - Brice BERNARD (brikou) - - David Maicher (dmaicher) - Baptiste Clavié (talus) - marc.weistroff - lenar @@ -112,17 +112,17 @@ Symfony is the result of the work of many people who made the code better - Florian Voutzinos (florianv) - Colin Frei - Adrien Brault (adrienbrault) + - Tomáš Votruba (tomas_votruba) - Joshua Thijssen - Peter Kokot (maastermedia) - David Buchmann (dbu) - excelwebzone - - Tomáš Votruba (tomas_votruba) + - Grégoire Paris (greg0ire) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - - Grégoire Paris (greg0ire) - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) @@ -135,11 +135,11 @@ Symfony is the result of the work of many people who made the code better - Sebastian Hörl (blogsh) - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) + - Alex Pott - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) - - Alex Pott - Julien Falque (julienfalque) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) @@ -147,6 +147,7 @@ Symfony is the result of the work of many people who made the code better - Mikael Pajunen - Joel Wurtz (brouznouf) - Jérôme Vasseur (jvasseur) + - Chris Wilkinson (thewilkybarkid) - Oleg Voronkovich - Philipp Wahala (hifi) - Vyacheslav Pavlov @@ -169,7 +170,6 @@ Symfony is the result of the work of many people who made the code better - GDIBass - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - James Halsall (jaitsu) - - Chris Wilkinson (thewilkybarkid) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -213,8 +213,10 @@ Symfony is the result of the work of many people who made the code better - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Rui Marinho (ruimarinho) + - Niels Keurentjes (curry684) - Eugene Wissner - Julien Brochet (mewt) + - Gabriel Ostrolucký - Tristan Darricau (nicofuma) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) @@ -247,13 +249,11 @@ Symfony is the result of the work of many people who made the code better - Alessandro Chitolina - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) - - Niels Keurentjes (curry684) - Jordan Samouh (jordansamouh) - Jakub Kucharovic (jkucharovic) - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto - - Gabriel Ostrolucký - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -285,6 +285,7 @@ Symfony is the result of the work of many people who made the code better - Robert Kiss (kepten) - Roumen Damianoff (roumen) - Antonio J. García Lagar (ajgarlag) + - Benoît Burnichon (bburnichon) - Kim Hemsø Rasmussen (kimhemsoe) - Wouter Van Hecke - Jérôme Parmentier (lctrs) @@ -293,6 +294,9 @@ Symfony is the result of the work of many people who made the code better - Michael Holm (hollo) - Marc Weistroff (futurecat) - Christian Schmidt + - Yanick Witschi (toflar) + - Edi Modrić (emodric) + - Thomas Calvet (fancyweb) - Chad Sikorra (chadsikorra) - Chris Smith (cs278) - Florian Klein (docteurklein) @@ -309,6 +313,7 @@ Symfony is the result of the work of many people who made the code better - Wouter J - Ismael Ambrosi (iambrosi) - Baptiste Lafontaine + - François Pluchino (francoispluchino) - Aurelijus Valeiša (aurelijus) - Victor Bocharsky (bocharsky_bw) - Jan Decavele (jandc) @@ -347,11 +352,9 @@ Symfony is the result of the work of many people who made the code better - Damien Alexandre (damienalexandre) - Felix Labrecque - Yaroslav Kiliba + - Maxime Veber (nek-) - Terje Bråten - - Yanick Witschi (toflar) - Robbert Klarenbeek (robbertkl) - - Edi Modrić (emodric) - - Thomas Calvet (fancyweb) - JhonnyL - David Badura (davidbadura) - hossein zolfi (ocean) @@ -364,7 +367,6 @@ Symfony is the result of the work of many people who made the code better - Philipp Kräutli (pkraeutli) - Kirill chEbba Chebunin (chebba) - Greg Thornton (xdissent) - - Benoît Burnichon (bburnichon) - Costin Bereveanu (schniper) - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) @@ -372,7 +374,6 @@ Symfony is the result of the work of many people who made the code better - Hassan Amouhzi - Tamas Szijarto - Pavel Volokitin (pvolok) - - François Pluchino (francoispluchino) - Arthur de Moulins (4rthem) - Nicolas Dewez (nicolas_dewez) - Endre Fejes @@ -452,7 +453,6 @@ Symfony is the result of the work of many people who made the code better - Zander Baldwin - Adam Harvey - Anton Bakai - - Maxime Veber (nek-) - Alex Bakhturin - Alexander Obuhovich (aik099) - boombatower @@ -575,6 +575,7 @@ Symfony is the result of the work of many people who made the code better - Hany el-Kerdany - Wang Jingyu - Åsmund Garfors + - Gunnstein Lye (glye) - Maxime Douailin - Jean Pasdeloup (pasdeloup) - Benjamin Cremer (bcremer) @@ -587,6 +588,7 @@ Symfony is the result of the work of many people who made the code better - Sebastian Marek (proofek) - Erkhembayar Gantulga (erheme318) - Michal Trojanowski + - Mateusz Sip - David Fuhr - Kamil Kokot (pamil) - Aurimas Niekis (gcds) @@ -648,6 +650,8 @@ Symfony is the result of the work of many people who made the code better - Richard van den Brand (ricbra) - develop - VJ + - Delf Tonder (leberknecht) + - Sullivan SENECHAL (soullivaneuh) - Mark Sonnabaum - Richard Quadling - jochenvdv @@ -801,6 +805,7 @@ Symfony is the result of the work of many people who made the code better - Jacques Moati - Balazs Csaba (balazscsaba2006) - Douglas Reith (douglas_reith) + - Forfarle (forfarle) - Harry Walter (haswalt) - Johnson Page (jwpage) - Ruben Gonzalez (rubenruateltek) @@ -930,6 +935,7 @@ Symfony is the result of the work of many people who made the code better - benatespina (benatespina) - Denis Kop - jfcixmedia + - Nikita Konstantinov - Martijn Evers - Benjamin Paap (benjaminpaap) - Christian @@ -975,6 +981,7 @@ Symfony is the result of the work of many people who made the code better - Jeremy Bush - wizhippo - Viacheslav Sychov + - Matt Brunt - Carlos Ortega Huetos - rpg600 - Péter Buri (burci) @@ -1026,6 +1033,7 @@ Symfony is the result of the work of many people who made the code better - Felicitus - Krzysztof Przybyszewski - Paul Matthews + - Vacheslav Silyutin - Juan Traverso - Alain Flaus (halundra) - Tarjei Huse (tarjei) @@ -1070,7 +1078,6 @@ Symfony is the result of the work of many people who made the code better - Sebastian Göttschkes (sgoettschkes) - Tatsuya Tsuruoka - Ross Tuck - - Gunnstein Lye (glye) - Kévin Gomez (kevin) - azine - Dawid Sajdak @@ -1126,6 +1133,7 @@ Symfony is the result of the work of many people who made the code better - Kim Laï Trinh - Jason Desrosiers - m.chwedziak + - Andreas Frömer - Philip Frank - Lance McNearney - Gonzalo Vilaseca (gonzalovilaseca) @@ -1144,7 +1152,6 @@ Symfony is the result of the work of many people who made the code better - WedgeSama - Felds Liscia - Chihiro Adachi (chihiro-adachi) - - Sullivan SENECHAL - Tadcka - Beth Binkovitz - Gonzalo Míguez @@ -1202,6 +1209,7 @@ Symfony is the result of the work of many people who made the code better - Simon Neidhold - Xavier HAUSHERR - Valentin VALCIU + - Jeremiah VALERIE - Kevin Dew - James Cowgill - 1ma (jautenim) @@ -1251,6 +1259,7 @@ Symfony is the result of the work of many people who made the code better - natechicago - Jonathan Poston - Adrian Olek (adrianolek) + - Jody Mickey (jwmickey) - Przemysław Piechota (kibao) - Leonid Terentyev (li0n) - ryunosuke @@ -1260,6 +1269,7 @@ Symfony is the result of the work of many people who made the code better - Iwan van Staveren (istaveren) - Povilas S. (povilas) - pborreli + - Boris Betzholz - Eric Caron - 2manypeople - Wing @@ -1409,6 +1419,7 @@ Symfony is the result of the work of many people who made the code better - vlakoff - bertillon - Bertalan Attila + - AmsTaFF (amstaff) - Yannick Bensacq (cibou) - Frédéric G. Marand (fgm) - Freek Van der Herten (freekmurze) @@ -1514,6 +1525,7 @@ Symfony is the result of the work of many people who made the code better - Javier Núñez Berrocoso (javiernuber) - Jelle Bekker (jbekker) - Ian Jenkins (jenkoian) + - Giovanni Albero (johntree) - Jorge Martin (jorgemartind) - Joeri Verdeyen (jverdeyen) - Dmitrii Poddubnyi (karser) @@ -1560,6 +1572,7 @@ Symfony is the result of the work of many people who made the code better - Ismail Asci (ismailasci) - Simon CONSTANS (kosssi) - Kristof Van Cauwenbergh (kristofvc) + - Dennis Langen (nijusan) - Paulius Jarmalavičius (pjarmalavicius) - Ramon Henrique Ornelas (ramonornela) - Ricardo de Vries (ricknox) @@ -1598,6 +1611,7 @@ Symfony is the result of the work of many people who made the code better - lol768 - jamogon - Vyacheslav Slinko + - Jakub Chábek - Johannes - Jörg Rühl - wesleyh @@ -1606,6 +1620,7 @@ Symfony is the result of the work of many people who made the code better - Michael Genereux - patrick-mcdougle - Dariusz Czech + - Jack Wright - Anonymous User - Paweł Tomulik - Eric J. Duran @@ -1728,7 +1743,6 @@ Symfony is the result of the work of many people who made the code better - Fabien D. (fabd) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) - - Forfarle (forfarle) - Yohan Giarelli (frequence-web) - Gerry Vandermaesen (gerryvdm) - Ghazy Ben Ahmed (ghazy) From 87580b1fd2620f50b92da9e17f201c8988496360 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Jan 2018 11:08:39 +0100 Subject: [PATCH 07/68] updated VERSION for 2.7.41 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index afbd8159996f3..82bd5ea5d88c5 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.41-DEV'; + const VERSION = '2.7.41'; const VERSION_ID = 20741; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 41; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 1ee3950b7310ab892531e4fc43961b448cf2bd28 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Jan 2018 11:46:38 +0100 Subject: [PATCH 08/68] bumped Symfony version to 2.7.42 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 82bd5ea5d88c5..159bde4d1bccc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.41'; - const VERSION_ID = 20741; + const VERSION = '2.7.42-DEV'; + const VERSION_ID = 20742; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 41; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 42; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From d5375d01dd3328b3946b729b744d498674f96c20 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Jan 2018 12:40:56 +0100 Subject: [PATCH 09/68] bumped Symfony version to 2.8.35 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f2db06634cca4..7f61bdc645e80 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.34'; - const VERSION_ID = 20834; + const VERSION = '2.8.35-DEV'; + const VERSION_ID = 20835; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 34; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 35; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 35f98e208962d2d40f91ada5c3c994d2edc79b83 Mon Sep 17 00:00:00 2001 From: Greg Anderson Date: Fri, 19 Jan 2018 15:19:59 -0800 Subject: [PATCH 10/68] Follow-on to #25825: Fix edge case in getParameterOption. Add one test to demonstrate getParameterOption fix. Add several tests to demonstrate current limitations in hasParameterOption. --- .../Component/Console/Input/ArgvInput.php | 19 +++++++---- .../Console/Input/InputInterface.php | 4 +++ .../Console/Tests/Input/ArgvInputTest.php | 32 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index c2f533eb36798..da064598d0741 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -279,7 +279,11 @@ public function hasParameterOption($values) foreach ($this->tokens as $token) { foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ($token === $value || 0 === strpos($token, $leading)) { return true; } } @@ -300,13 +304,16 @@ public function getParameterOption($values, $default = false) $token = array_shift($tokens); foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - if (false !== $pos = strpos($token, '=')) { - return substr($token, $pos + 1); - } - + if ($token === $value) { return array_shift($tokens); } + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if (0 === strpos($token, $leading)) { + return substr($token, strlen($leading)); + } } } diff --git a/src/Symfony/Component/Console/Input/InputInterface.php b/src/Symfony/Component/Console/Input/InputInterface.php index 9de6e3a409830..ac14de7d6f85f 100644 --- a/src/Symfony/Component/Console/Input/InputInterface.php +++ b/src/Symfony/Component/Console/Input/InputInterface.php @@ -30,6 +30,8 @@ public function getFirstArgument(); * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. * * @param string|array $values The values to look for in the raw parameters (can be an array) * @@ -42,6 +44,8 @@ public function hasParameterOption($values); * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 1fe21d0f6c1a8..04f5ce3157c44 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -296,6 +296,10 @@ public function testHasParameterOption() $input = new ArgvInput(array('cli.php', '-f', 'foo')); $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '-etest')); + $this->assertTrue($input->hasParameterOption('-e'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $this->assertFalse($input->hasParameterOption('-s'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '--foo', 'foo')); $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input'); @@ -306,6 +310,33 @@ public function testHasParameterOption() $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input'); } + public function testHasParameterOptionEdgeCasesAndLimitations() + { + $input = new ArgvInput(array('cli.php', '-fh')); + // hasParameterOption does not know if the previous short option, -f, + // takes a value or not. If -f takes a value, then -fh does NOT include + // -h; Otherwise it does. Since we do not know which short options take + // values, hasParameterOption does not support this use-case. + $this->assertFalse($input->hasParameterOption('-h'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // hasParameterOption does detect that `-fh` contains `-f`, since + // `-f` is the first short option in the set. + $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // The test below happens to pass, although it might make more sense + // to disallow it, and require the use of + // $input->hasParameterOption('-f') && $input->hasParameterOption('-h') + // instead. + $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + // In theory, if -fh is supported, then -hf should also work. + // However, this is not supported. + $this->assertFalse($input->hasParameterOption('-hf'), '->hasParameterOption() returns true if the given short option is in the raw input'); + + $input = new ArgvInput(array('cli.php', '-f', '-h')); + // If hasParameterOption('-fh') is supported for 'cli.php -fh', then + // one might also expect that it should also be supported for + // 'cli.php -f -h'. However, this is not supported. + $this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + } + public function testToString() { $input = new ArgvInput(array('cli.php', '-f', 'foo')); @@ -327,6 +358,7 @@ public function testGetParameterOptionEqualSign($argv, $key, $expected) public function provideGetParameterOptionValues() { return array( + array(array('app/console', 'foo:bar', '-edev'), '-e', 'dev'), array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'dev'), array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'dev'), array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'dev'), From 926b1bee1828f6a01d93a3926b756e096c5042d2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 Jan 2018 16:11:54 +0100 Subject: [PATCH 11/68] [Debug] Fix bad registration of exception handler, leading to mem leak --- src/Symfony/Component/Debug/ErrorHandler.php | 13 ++++++++++++- .../Component/Debug/Tests/ErrorHandlerTest.php | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 6a15f7b368307..8875e03e8442b 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -149,9 +149,20 @@ public static function register($handler = null, $replace = true) } if (!$replace && $prev) { restore_error_handler(); + $handlerIsRegistered = is_array($prev) && $handler === $prev[0]; + } else { + $handlerIsRegistered = true; } - if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] === $handler) { + if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) { restore_exception_handler(); + if (!$handlerIsRegistered) { + $handler = $prev[0]; + } elseif ($handler !== $prev[0] && $replace) { + set_exception_handler(array($handler, 'handleException')); + $p = $prev[0]->setExceptionHandler(null); + $handler->setExceptionHandler($p); + $prev[0]->setExceptionHandler($p); + } } else { $handler->setExceptionHandler($prev); } diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 264dc701e7e2e..f2d0fc8b0bc85 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -34,7 +34,7 @@ public function testRegister() $newHandler = new ErrorHandler(); - $this->assertSame($newHandler, ErrorHandler::register($newHandler, false)); + $this->assertSame($handler, ErrorHandler::register($newHandler, false)); $h = set_error_handler('var_dump'); restore_error_handler(); $this->assertSame(array($handler, 'handleError'), $h); From 5bbb77b866fc0fb50ef762e572f9344267eaebf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=9D=A6=E7=B1=B3?= Date: Tue, 30 Jan 2018 23:53:25 +0800 Subject: [PATCH 12/68] support sapi_windows_vt100_support for php 7.2+ --- src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php | 3 ++- src/Symfony/Component/Console/Output/StreamOutput.php | 3 ++- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index dae4759134c2f..f73690db00553 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -161,7 +161,8 @@ private static function hasColorSupport() { if ('\\' === DIRECTORY_SEPARATOR) { return - '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD + defined('STDOUT') && function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) + || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index e547c3a6c0b9f..d32b1cfb54cae 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -90,7 +90,8 @@ protected function hasColorSupport() { if (DIRECTORY_SEPARATOR === '\\') { return - '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD + function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->stream) + || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 107a2a438d35e..689ada77c2460 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -450,7 +450,8 @@ protected function supportsColors() if ('\\' === DIRECTORY_SEPARATOR) { static::$defaultColors = @( - '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD + function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->outputStream) + || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM') From 3288fb0d1778039351cfd5fbed00907adc46c834 Mon Sep 17 00:00:00 2001 From: Joachim Krempel Date: Tue, 30 Jan 2018 12:45:31 +0100 Subject: [PATCH 13/68] [WebProfilerBundle] Increase retry delays between toolbarAction ajax calls --- .../Resources/views/Profiler/base_js.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index a1b9c4ffd992b..cde7a4c685832 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -32,7 +32,7 @@ setTimeout(function(){ options.maxTries--; request(url, onSuccess, onError, payload, options); - }, 500); + }, 1000); return null; } From 21bbad93f0a1561d7bd4c2788547c9a567cc0b3a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 30 Jan 2018 16:03:04 +0100 Subject: [PATCH 14/68] update test for Twig performance optimizations --- src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 4b356b2a8d655..2d4b13f0daecb 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -57,6 +57,10 @@ protected function getVariableGetterWithoutStrictCheck($name) protected function getVariableGetterWithStrictCheck($name) { + if (Environment::VERSION_ID > 20404) { + return sprintf('(isset($context["%s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%1$s" does not exist.\', 0, $this->source); })())', $name); + } + if (Environment::MAJOR_VERSION >= 2) { return sprintf('(isset($context["%s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%1$s" does not exist.\', 0, $this->getSourceContext()); })())', $name); } From ad593aef2fd616289049e93b909de8d4c1a842ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 Jan 2018 08:44:00 +0100 Subject: [PATCH 15/68] [Routing] Fix trailing slash redirection for non-safe verbs --- .../Matcher/Dumper/PhpMatcherDumper.php | 10 +- .../Tests/Fixtures/dumper/url_matcher1.php | 2 +- .../Tests/Fixtures/dumper/url_matcher2.php | 23 +++- .../Tests/Fixtures/dumper/url_matcher3.php | 2 +- .../DumpedRedirectableUrlMatcherTest.php | 43 +++++++ .../Tests/Matcher/DumpedUrlMatcherTest.php | 39 ++++++ .../Matcher/RedirectableUrlMatcherTest.php | 34 ++++-- .../Routing/Tests/Matcher/UrlMatcherTest.php | 111 +++++++++++------- 8 files changed, 203 insertions(+), 61 deletions(-) create mode 100644 src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php create mode 100644 src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 016021e259c5f..28ab3679f9fa8 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -101,7 +101,7 @@ public function match(\$rawPathinfo) \$allow = array(); \$pathinfo = rawurldecode(\$rawPathinfo); \$context = \$this->context; - \$request = \$this->request; + \$request = \$this->request ?: \$this->createRequest(\$pathinfo); $code @@ -283,7 +283,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren if ($hasTrailingSlash) { $code .= <<context->getMethod(), array('HEAD', 'GET'))) { + goto $gotoname; + } else { return \$this->redirect(\$rawPathinfo.'/', '$name'); } @@ -329,7 +333,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } $code .= " }\n"; - if ($methods) { + if ($methods || $hasTrailingSlash) { $code .= " $gotoname:\n"; } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index 6451192d1877e..a87f063af57ac 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -20,7 +20,7 @@ public function match($rawPathinfo) $allow = array(); $pathinfo = rawurldecode($rawPathinfo); $context = $this->context; - $request = $this->request; + $request = $this->request ?: $this->createRequest($pathinfo); // foo if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#s', $pathinfo, $matches)) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index 9b44eb920deab..7ec89b8e2f457 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -20,7 +20,7 @@ public function match($rawPathinfo) $allow = array(); $pathinfo = rawurldecode($rawPathinfo); $context = $this->context; - $request = $this->request; + $request = $this->request ?: $this->createRequest($pathinfo); // foo if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#s', $pathinfo, $matches)) { @@ -66,23 +66,33 @@ public function match($rawPathinfo) // baz3 if ('/test/baz3' === rtrim($pathinfo, '/')) { - if (substr($pathinfo, -1) !== '/') { + if ('/' === substr($pathinfo, -1)) { + // no-op + } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + goto not_baz3; + } else { return $this->redirect($rawPathinfo.'/', 'baz3'); } return array('_route' => 'baz3'); } + not_baz3: } // baz4 if (preg_match('#^/test/(?P[^/]++)/?$#s', $pathinfo, $matches)) { - if (substr($pathinfo, -1) !== '/') { + if ('/' === substr($pathinfo, -1)) { + // no-op + } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + goto not_baz4; + } else { return $this->redirect($rawPathinfo.'/', 'baz4'); } return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); } + not_baz4: // baz5 if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { @@ -170,12 +180,17 @@ public function match($rawPathinfo) // hey if ('/multi/hey' === rtrim($pathinfo, '/')) { - if (substr($pathinfo, -1) !== '/') { + if ('/' === substr($pathinfo, -1)) { + // no-op + } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + goto not_hey; + } else { return $this->redirect($rawPathinfo.'/', 'hey'); } return array('_route' => 'hey'); } + not_hey: } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index 04043273df740..f5234dd43bbec 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -20,7 +20,7 @@ public function match($rawPathinfo) $allow = array(); $pathinfo = rawurldecode($rawPathinfo); $context = $this->context; - $request = $this->request; + $request = $this->request ?: $this->createRequest($pathinfo); if (0 === strpos($pathinfo, '/rootprefix')) { // static diff --git a/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php new file mode 100644 index 0000000000000..28f65aeeb5aa7 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + static $i = 0; + + $class = 'DumpedRedirectableUrlMatcher'.++$i; + $dumper = new PhpMatcherDumper($routes); + $dumpedRoutes = eval('?>'.$dumper->dump(array('class' => $class, 'base_class' => 'Symfony\Component\Routing\Tests\Matcher\TestDumpedRedirectableUrlMatcher'))); + + return $this->getMockBuilder($class) + ->setConstructorArgs(array($context ?: new RequestContext())) + ->setMethods(array('redirect')) + ->getMock(); + } +} + +class TestDumpedRedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return array(); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php new file mode 100644 index 0000000000000..cc7eb8e2d7307 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class DumpedUrlMatcherTest extends UrlMatcherTest +{ + /** + * @expectedException \LogicException + * @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface. + */ + public function testSchemeRequirement() + { + parent::testSchemeRequirement(); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + static $i = 0; + + $class = 'DumpedUrlMatcher'.++$i; + $dumper = new PhpMatcherDumper($routes); + $dumpedRoutes = eval('?>'.$dumper->dump(array('class' => $class))); + + return new $class($context ?: new RequestContext()); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php index 0b5bb0dc78cac..fc7683903fc6b 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -11,20 +11,19 @@ namespace Symfony\Component\Routing\Tests\Matcher; -use PHPUnit\Framework\TestCase; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; -class RedirectableUrlMatcherTest extends TestCase +class RedirectableUrlMatcherTest extends UrlMatcherTest { public function testRedirectWhenNoSlash() { $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/')); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); - $matcher->expects($this->once())->method('redirect'); + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->will($this->returnValue(array())); $matcher->match('/foo'); } @@ -38,7 +37,7 @@ public function testRedirectWhenNoSlashForNonSafeMethod() $context = new RequestContext(); $context->setMethod('POST'); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, $context)); + $matcher = $this->getUrlMatcher($coll, $context); $matcher->match('/foo'); } @@ -47,7 +46,7 @@ public function testSchemeRedirectRedirectsToFirstScheme() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('FTP', 'HTTPS'))); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->once()) ->method('redirect') @@ -62,11 +61,10 @@ public function testNoSchemaRedirectIfOnOfMultipleSchemesMatches() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https', 'http'))); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->never()) - ->method('redirect') - ; + ->method('redirect'); $matcher->match('/foo'); } @@ -75,8 +73,22 @@ public function testRedirectPreservesUrlEncoding() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo:bar/')); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); - $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/'); + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/')->willReturn(array()); $matcher->match('/foo%3Abar'); } + + public function testSchemeRequirement() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https'))); + $matcher = $this->getUrlMatcher($coll, new RequestContext()); + $matcher->expects($this->once())->method('redirect')->with('/foo', 'foo', 'https')->willReturn(array('_route' => 'foo')); + $this->assertSame(array('_route' => 'foo'), $matcher->match('/foo')); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($routes, $context ?: new RequestContext())); + } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 9fd53e9814496..de79a073eaf0c 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -26,7 +26,7 @@ public function testNoMethodSoAllowed() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertInternalType('array', $matcher->match('/foo')); } @@ -35,7 +35,7 @@ public function testMethodNotAllowed() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('post'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); try { $matcher->match('/foo'); @@ -50,7 +50,7 @@ public function testHeadAllowedWhenRequirementContainsGet() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('get'))); - $matcher = new UrlMatcher($coll, new RequestContext('', 'head')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'head')); $this->assertInternalType('array', $matcher->match('/foo')); } @@ -60,7 +60,7 @@ public function testMethodNotAllowedAggregatesAllowedMethods() $coll->add('foo1', new Route('/foo', array(), array(), array(), '', array(), array('post'))); $coll->add('foo2', new Route('/foo', array(), array(), array(), '', array(), array('put', 'delete'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); try { $matcher->match('/foo'); @@ -75,7 +75,7 @@ public function testMatch() // test the patterns are matched and parameters are returned $collection = new RouteCollection(); $collection->add('foo', new Route('/foo/{bar}')); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); try { $matcher->match('/no-match'); $this->fail(); @@ -86,17 +86,17 @@ public function testMatch() // test that defaults are merged $collection = new RouteCollection(); $collection->add('foo', new Route('/foo/{bar}', array('def' => 'test'))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz')); // test that route "method" is ignored if no method is given in the context $collection = new RouteCollection(); $collection->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('get', 'head'))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertInternalType('array', $matcher->match('/foo')); // route does not match with POST method context - $matcher = new UrlMatcher($collection, new RequestContext('', 'post')); + $matcher = $this->getUrlMatcher($collection, new RequestContext('', 'post')); try { $matcher->match('/foo'); $this->fail(); @@ -104,28 +104,28 @@ public function testMatch() } // route does match with GET or HEAD method context - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertInternalType('array', $matcher->match('/foo')); - $matcher = new UrlMatcher($collection, new RequestContext('', 'head')); + $matcher = $this->getUrlMatcher($collection, new RequestContext('', 'head')); $this->assertInternalType('array', $matcher->match('/foo')); // route with an optional variable as the first segment $collection = new RouteCollection(); $collection->add('bar', new Route('/{bar}/foo', array('bar' => 'bar'), array('bar' => 'foo|bar'))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/bar/foo')); $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo/foo')); $collection = new RouteCollection(); $collection->add('bar', new Route('/{bar}', array('bar' => 'bar'), array('bar' => 'foo|bar'))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo')); $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/')); // route with only optional variables $collection = new RouteCollection(); $collection->add('bar', new Route('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar'), array())); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'bar', 'foo' => 'foo', 'bar' => 'bar'), $matcher->match('/')); $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'bar'), $matcher->match('/a')); $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'b'), $matcher->match('/a/b')); @@ -138,7 +138,7 @@ public function testMatchWithPrefixes() $collection->addPrefix('/b'); $collection->addPrefix('/a'); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'foo', 'foo' => 'foo'), $matcher->match('/a/b/foo')); } @@ -149,7 +149,7 @@ public function testMatchWithDynamicPrefix() $collection->addPrefix('/b'); $collection->addPrefix('/{_locale}'); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo')); } @@ -158,7 +158,7 @@ public function testMatchSpecialRouteName() $collection = new RouteCollection(); $collection->add('$péß^a|', new Route('/bar')); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => '$péß^a|'), $matcher->match('/bar')); } @@ -166,9 +166,9 @@ public function testMatchNonAlpha() { $collection = new RouteCollection(); $chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-'; - $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+'))); + $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+'), array('utf8' => true))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.rawurlencode($chars).'/bar')); $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25')).'/bar')); } @@ -178,7 +178,7 @@ public function testMatchWithDotMetacharacterInRequirements() $collection = new RouteCollection(); $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '.+'))); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'foo', 'foo' => "\n"), $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched'); } @@ -192,7 +192,7 @@ public function testMatchOverriddenRoute() $collection->addCollection($collection1); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); $this->assertEquals(array('_route' => 'foo'), $matcher->match('/foo1')); $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\ResourceNotFoundException'); @@ -205,12 +205,12 @@ public function testMatchRegression() $coll->add('foo', new Route('/foo/{foo}')); $coll->add('bar', new Route('/foo/bar/{foo}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('foo' => 'bar', '_route' => 'bar'), $matcher->match('/foo/bar/bar')); $collection = new RouteCollection(); $collection->add('foo', new Route('/{bar}')); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); try { $matcher->match('/'); $this->fail(); @@ -223,7 +223,7 @@ public function testDefaultRequirementForOptionalVariables() $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}', array('page' => 'index', '_format' => 'html'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('page' => 'my-page', '_format' => 'xml', '_route' => 'test'), $matcher->match('/my-page.xml')); } @@ -232,7 +232,7 @@ public function testMatchingIsEager() $coll = new RouteCollection(); $coll->add('test', new Route('/{foo}-{bar}-', array(), array('foo' => '.+', 'bar' => '.+'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('foo' => 'text1-text2-text3', 'bar' => 'text4', '_route' => 'test'), $matcher->match('/text1-text2-text3-text4-')); } @@ -241,7 +241,7 @@ public function testAdjacentVariables() $coll = new RouteCollection(); $coll->add('test', new Route('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => 'y|Y'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); // 'w' eagerly matches as much as possible and the other variables match the remaining chars. // This also shows that the variables w-z must all exclude the separating char (the dot '.' in this case) by default requirement. // Otherwise they would also consume '.xml' and _format would never match as it's an optional variable. @@ -260,7 +260,7 @@ public function testOptionalVariableWithNoRealSeparator() { $coll = new RouteCollection(); $coll->add('test', new Route('/get{what}', array('what' => 'All'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('what' => 'All', '_route' => 'test'), $matcher->match('/get')); $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSites')); @@ -275,7 +275,7 @@ public function testRequiredVariableWithNoRealSeparator() { $coll = new RouteCollection(); $coll->add('test', new Route('/get{what}Suffix')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSitesSuffix')); } @@ -284,7 +284,7 @@ public function testDefaultRequirementOfVariable() { $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('page' => 'index', '_format' => 'mobile.html', '_route' => 'test'), $matcher->match('/index.mobile.html')); } @@ -296,7 +296,7 @@ public function testDefaultRequirementOfVariableDisallowsSlash() { $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/index.sl/ash'); } @@ -308,7 +308,7 @@ public function testDefaultRequirementOfVariableDisallowsNextSeparator() { $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}', array(), array('_format' => 'html|xml'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/do.t.html'); } @@ -320,7 +320,7 @@ public function testSchemeRequirement() { $coll = new RouteCollection(); $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/foo'); } @@ -333,7 +333,7 @@ public function testCondition() $route = new Route('/foo'); $route->setCondition('context.getMethod() == "POST"'); $coll->add('foo', $route); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/foo'); } @@ -343,7 +343,7 @@ public function testRequestCondition() $route = new Route('/foo/{bar}'); $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); $coll->add('foo', $route); - $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('/sub/front.php')); $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); } @@ -352,7 +352,7 @@ public function testDecodeOnce() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{foo}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('foo' => 'bar%23', '_route' => 'foo'), $matcher->match('/foo/bar%2523')); } @@ -368,7 +368,7 @@ public function testCannotRelyOnPrefix() $coll->addCollection($subColl); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $this->assertEquals(array('_route' => 'bar'), $matcher->match('/new')); } @@ -377,7 +377,7 @@ public function testWithHost() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); } @@ -388,10 +388,10 @@ public function testWithHostOnRouteCollection() $coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net')); $coll->setHost('{locale}.example.com'); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar')); } @@ -403,7 +403,7 @@ public function testWithOutHostHostDoesNotMatch() $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'example.com')); $matcher->match('/foo/bar'); } @@ -415,7 +415,7 @@ public function testPathIsCaseSensitive() $coll = new RouteCollection(); $coll->add('foo', new Route('/locale', array(), array('locale' => 'EN|FR|DE'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/en'); } @@ -424,7 +424,36 @@ public function testHostIsCaseInsensitive() $coll = new RouteCollection(); $coll->add('foo', new Route('/', array(), array('locale' => 'EN|FR|DE'), array(), '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $this->assertEquals(array('_route' => 'foo', 'locale' => 'en'), $matcher->match('/')); } + + public function testNestedCollections() + { + $coll = new RouteCollection(); + + $subColl = new RouteCollection(); + $subColl->add('a', new Route('/a')); + $subColl->add('b', new Route('/b')); + $subColl->add('c', new Route('/c')); + $subColl->addPrefix('/p'); + $coll->addCollection($subColl); + + $coll->add('baz', new Route('/{baz}')); + + $subColl = new RouteCollection(); + $subColl->add('buz', new Route('/buz')); + $subColl->addPrefix('/prefix'); + $coll->addCollection($subColl); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(array('_route' => 'a'), $matcher->match('/p/a')); + $this->assertEquals(array('_route' => 'baz', 'baz' => 'p'), $matcher->match('/p')); + $this->assertEquals(array('_route' => 'buz'), $matcher->match('/prefix/buz')); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return new UrlMatcher($routes, $context ?: new RequestContext()); + } } From 5733e02960f683f2db278980ba96d80c2e013622 Mon Sep 17 00:00:00 2001 From: Victor Bocharsky Date: Thu, 28 Dec 2017 16:08:38 +0200 Subject: [PATCH 16/68] [Intl] Fixed the broken link --- src/Symfony/Component/Intl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Intl/README.md b/src/Symfony/Component/Intl/README.md index 806c6275e83dd..9a9cb9b45614e 100644 --- a/src/Symfony/Component/Intl/README.md +++ b/src/Symfony/Component/Intl/README.md @@ -5,7 +5,7 @@ A PHP replacement layer for the C intl extension that also provides access to the localization data of the ICU library. The replacement layer is limited to the locale "en". If you want to use other -locales, you should [install the intl PHP extension] [0] instead. +locales, you should [install the intl PHP extension][0] instead. Resources --------- From e0132cc5d769c58b55013c45e49141ad838d19d5 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Fri, 2 Feb 2018 12:17:55 +0100 Subject: [PATCH 17/68] Update MongoDB extension on travis to make the builds green again. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2a3e945695143..c4eab3432309d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,8 +100,6 @@ before_install: [[ $PHP = 5.* ]] && echo extension = memcache.so >> $INI if [[ $PHP = 5.* ]]; then echo extension = mongo.so >> $INI - elif [[ $PHP = 7.* ]]; then - echo extension = mongodb.so >> $INI fi # Matrix lines for intermediate PHP versions are skipped for pull requests @@ -127,6 +125,7 @@ before_install: tfold ext.apcu4 'echo yes | pecl install -f apcu-4.0.11' elif [[ ! $skip && $PHP = 7.* ]]; then tfold ext.apcu5 'echo yes | pecl install -f apcu-5.1.6' + tfold ext.mongodb pecl install -f mongodb-1.4.0RC1 fi install: From d6f4f5129e24d27e64b1fa4b502bf5aa88215cca Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 3 Feb 2018 01:09:36 +0100 Subject: [PATCH 18/68] Removed unused parameter from flattenDataProvider(). --- .../Debug/Tests/Exception/FlattenExceptionTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php index d3b9ab2eb770a..269abf0f7bd63 100644 --- a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php @@ -105,7 +105,7 @@ public function testHeadersForHttpException() /** * @dataProvider flattenDataProvider */ - public function testFlattenHttpException(\Exception $exception, $statusCode) + public function testFlattenHttpException(\Exception $exception) { $flattened = FlattenException::create($exception); $flattened2 = FlattenException::create($exception); @@ -120,7 +120,7 @@ public function testFlattenHttpException(\Exception $exception, $statusCode) /** * @dataProvider flattenDataProvider */ - public function testPrevious(\Exception $exception, $statusCode) + public function testPrevious(\Exception $exception) { $flattened = FlattenException::create($exception); $flattened2 = FlattenException::create($exception); @@ -167,7 +167,7 @@ public function testFile(\Exception $exception) /** * @dataProvider flattenDataProvider */ - public function testToArray(\Exception $exception, $statusCode) + public function testToArray(\Exception $exception) { $flattened = FlattenException::create($exception); $flattened->setTrace(array(), 'foo.php', 123); @@ -187,7 +187,7 @@ public function testToArray(\Exception $exception, $statusCode) public function flattenDataProvider() { return array( - array(new \Exception('test', 123), 500), + array(new \Exception('test', 123)), ); } From 76b40dc10e46814fd329d0cf1dd285820a3e822a Mon Sep 17 00:00:00 2001 From: Arnaud CHASSEUX Date: Wed, 4 Feb 2015 18:46:52 +0100 Subject: [PATCH 19/68] [CssSelector] For AND operator, the left operand should have parentheses, not only right operand --- .../CssSelector/Tests/CssSelectorTest.php | 2 +- .../CssSelector/Tests/XPath/TranslatorTest.php | 16 +++++++++------- .../Component/CssSelector/XPath/XPathExpr.php | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php b/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php index f1dee1ee11ee9..e05d398847a57 100644 --- a/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php +++ b/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php @@ -48,7 +48,7 @@ public function getCssToXPathWithoutPrefixTestData() array('h1', 'h1'), array('foo|h1', 'foo:h1'), array('h1, h2, h3', 'h1 | h2 | h3'), - array('h1:nth-child(3n+1)', "*/*[name() = 'h1' and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"), + array('h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"), array('h1 > p', 'h1/p'), array('h1#foo', "h1[@id = 'foo']"), array('h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"), diff --git a/src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php b/src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php index 218a3b43c1a78..519417835cefe 100644 --- a/src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php +++ b/src/Symfony/Component/CssSelector/Tests/XPath/TranslatorTest.php @@ -102,18 +102,20 @@ public function getCssToXPathTestData() array('e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"), array('e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"), array('e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"), + array('e[foo!="bar"]', "e[not(@foo) or @foo != 'bar']"), + array('e[foo!="bar"][foo!="baz"]', "e[(not(@foo) or @foo != 'bar') and (not(@foo) or @foo != 'baz')]"), array('e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"), - array('e:nth-child(1)', "*/*[name() = 'e' and (position() = 1)]"), - array('e:nth-last-child(1)', "*/*[name() = 'e' and (position() = last() - 0)]"), - array('e:nth-last-child(2n+2)', "*/*[name() = 'e' and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"), + array('e:nth-child(1)', "*/*[(name() = 'e') and (position() = 1)]"), + array('e:nth-last-child(1)', "*/*[(name() = 'e') and (position() = last() - 0)]"), + array('e:nth-last-child(2n+2)', "*/*[(name() = 'e') and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"), array('e:nth-of-type(1)', '*/e[position() = 1]'), array('e:nth-last-of-type(1)', '*/e[position() = last() - 0]'), array('div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"), - array('e:first-child', "*/*[name() = 'e' and (position() = 1)]"), - array('e:last-child', "*/*[name() = 'e' and (position() = last())]"), + array('e:first-child', "*/*[(name() = 'e') and (position() = 1)]"), + array('e:last-child', "*/*[(name() = 'e') and (position() = last())]"), array('e:first-of-type', '*/e[position() = 1]'), array('e:last-of-type', '*/e[position() = last()]'), - array('e:only-child', "*/*[name() = 'e' and (last() = 1)]"), + array('e:only-child', "*/*[(name() = 'e') and (last() = 1)]"), array('e:only-of-type', 'e[last() = 1]'), array('e:empty', 'e[not(*) and not(string-length())]'), array('e:EmPTY', 'e[not(*) and not(string-length())]'), @@ -127,7 +129,7 @@ public function getCssToXPathTestData() array('e:nOT(*)', 'e[0]'), array('e f', 'e/descendant-or-self::*/f'), array('e > f', 'e/f'), - array('e + f', "e/following-sibling::*[name() = 'f' and (position() = 1)]"), + array('e + f', "e/following-sibling::*[(name() = 'f') and (position() = 1)]"), array('e ~ f', 'e/following-sibling::f'), array('div#container p', "div[@id = 'container']/descendant-or-self::*/p"), ); diff --git a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php index c0d2bd55a5a03..1c7aead7ed8bd 100644 --- a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php +++ b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php @@ -57,7 +57,7 @@ public function getElement() */ public function addCondition($condition) { - $this->condition = $this->condition ? sprintf('%s and (%s)', $this->condition, $condition) : $condition; + $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition; return $this; } @@ -101,7 +101,7 @@ public function addStarPrefix() * * @return $this */ - public function join($combiner, XPathExpr $expr) + public function join($combiner, self $expr) { $path = $this->__toString().$combiner; From 48db494b19e3fbddeffef0b77a52b6414f5057a0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 3 Feb 2018 15:55:47 +0100 Subject: [PATCH 20/68] fix merge --- .../Component/CssSelector/Tests/CssSelectorConverterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php b/src/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php index a27fadfef1e70..a3eea7ad21869 100644 --- a/src/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php +++ b/src/Symfony/Component/CssSelector/Tests/CssSelectorConverterTest.php @@ -59,7 +59,7 @@ public function getCssToXPathWithoutPrefixTestData() array('h1', 'h1'), array('foo|h1', 'foo:h1'), array('h1, h2, h3', 'h1 | h2 | h3'), - array('h1:nth-child(3n+1)', "*/*[name() = 'h1' and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"), + array('h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"), array('h1 > p', 'h1/p'), array('h1#foo', "h1[@id = 'foo']"), array('h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"), From b9def8ab5043149a8905dae143c543b6d5484e2b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 4 Feb 2018 10:26:21 +0100 Subject: [PATCH 21/68] [travis] cache compiled php extensions --- .travis.yml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c4eab3432309d..7f13d5b60cea3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ cache: directories: - .phpunit - php-$MIN_PHP + - php-ext services: mongodb @@ -102,6 +103,23 @@ before_install: echo extension = mongo.so >> $INI fi + # tpecl is a helper to compile and cache php extensions + tpecl () { + local ext_name=$1 + local ext_so=$2 + local ext_dir=$(php -r "echo ini_get('extension_dir');") + local ext_cache=~/php-ext/$(basename $ext_dir)/$ext_name + + if [[ -e $ext_cache/$ext_so ]]; then + echo extension = $ext_cache/$ext_so >> $INI + else + mkdir -p $ext_cache + echo yes | pecl install -f $ext_name && + cp $ext_dir/$ext_so $ext_cache + fi + } + export -f tpecl + # Matrix lines for intermediate PHP versions are skipped for pull requests if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip @@ -120,12 +138,12 @@ before_install: - | # Install extra PHP extensions if [[ ! $skip && $PHP = 5.* ]]; then - ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") && - tfold ext.memcached pecl install -f memcached-2.1.0 && - tfold ext.apcu4 'echo yes | pecl install -f apcu-4.0.11' + ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") + tfold ext.memcached tpecl memcached-2.1.0 memcached.so + tfold ext.apcu tpecl apcu-4.0.11 apcu.so elif [[ ! $skip && $PHP = 7.* ]]; then - tfold ext.apcu5 'echo yes | pecl install -f apcu-5.1.6' - tfold ext.mongodb pecl install -f mongodb-1.4.0RC1 + tfold ext.apcu tpecl apcu-5.1.6 apcu.so + tfold ext.mongodb tpecl mongodb-1.4.0RC1 mongodb.so fi install: From f713a3e879b6d016254fe8b8275e99824146ffae Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Thu, 7 Dec 2017 10:40:47 +0100 Subject: [PATCH 22/68] Use the PCRE_DOLLAR_ENDONLY modifier in route regexes --- .../Console/Descriptor/ObjectsProvider.php | 13 ++++- .../Tests/Fixtures/Descriptor/route_1.json | 6 +- .../Tests/Fixtures/Descriptor/route_1.md | 6 +- .../Tests/Fixtures/Descriptor/route_1.txt | 6 +- .../Tests/Fixtures/Descriptor/route_1.xml | 6 +- .../Tests/Fixtures/Descriptor/route_2.json | 6 +- .../Tests/Fixtures/Descriptor/route_2.md | 6 +- .../Tests/Fixtures/Descriptor/route_2.txt | 6 +- .../Tests/Fixtures/Descriptor/route_2.xml | 6 +- .../Descriptor/route_collection_1.json | 12 ++-- .../Fixtures/Descriptor/route_collection_1.md | 12 ++-- .../Descriptor/route_collection_1.xml | 12 ++-- .../Component/Routing/RouteCompiler.php | 2 +- .../Tests/Fixtures/dumper/url_matcher1.php | 56 +++++++++---------- .../Tests/Fixtures/dumper/url_matcher2.php | 56 +++++++++---------- .../Tests/Fixtures/dumper/url_matcher3.php | 2 +- .../Routing/Tests/Matcher/UrlMatcherTest.php | 12 ++++ .../Routing/Tests/RouteCompilerTest.php | 44 +++++++-------- .../Component/Routing/Tests/RouteTest.php | 2 +- 19 files changed, 146 insertions(+), 125 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index d6fc8b24ad264..108e53a7dff28 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\CompiledRoute; use Symfony\Component\Routing\RouteCollection; class ObjectsProvider @@ -35,7 +36,7 @@ public static function getRouteCollections() public static function getRoutes() { return array( - 'route_1' => new Route( + 'route_1' => new RouteStub( '/hello/{name}', array('name' => 'Joseph'), array('name' => '[a-z]+'), @@ -44,7 +45,7 @@ public static function getRoutes() array('http', 'https'), array('get', 'head') ), - 'route_2' => new Route( + 'route_2' => new RouteStub( '/name/add', array(), array(), @@ -207,3 +208,11 @@ public static function staticMethod() { } } + +class RouteStub extends Route +{ + public function compile() + { + return new CompiledRoute('', '#PATH_REGEX#', array(), array(), '#HOST_REGEX#'); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.json index beac79f1f8758..1108109fb0b48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.json @@ -1,11 +1,11 @@ { "path": "\/hello\/{name}", - "pathRegex": "#^\/hello(?:\/(?P[a-z]+))?$#s", + "pathRegex": "#PATH_REGEX#", "host": "localhost", - "hostRegex": "#^localhost$#si", + "hostRegex": "#HOST_REGEX#", "scheme": "http|https", "method": "GET|HEAD", - "class": "Symfony\\Component\\Routing\\Route", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", "defaults": { "name": "Joseph" }, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.md index 5bfba18b2c814..c36d35c83e8ac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.md @@ -1,10 +1,10 @@ - Path: /hello/{name} -- Path Regex: #^/hello(?:/(?P[a-z]+))?$#s +- Path Regex: #PATH_REGEX# - Host: localhost -- Host Regex: #^localhost$#si +- Host Regex: #HOST_REGEX# - Scheme: http|https - Method: GET|HEAD -- Class: Symfony\Component\Routing\Route +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub - Defaults: - `name`: Joseph - Requirements: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt index 1c07ccde50119..ba7458d143c84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt @@ -1,10 +1,10 @@ Path /hello/{name} -Path Regex #^/hello(?:/(?P[a-z]+))?$#s +Path Regex #PATH_REGEX# Host localhost -Host Regex #^localhost$#si +Host Regex #HOST_REGEX# Scheme http|https Method GET|HEAD -Class Symfony\Component\Routing\Route +Class Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub Defaults name: Joseph Requirements name: [a-z]+ Options compiler_class: Symfony\Component\Routing\RouteCompiler diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.xml index b6040bdad160c..9ff531c92821a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.xml @@ -1,7 +1,7 @@ - - /hello/{name} - localhost + + /hello/{name} + localhost http https GET diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json index 58caf26d537e7..e190ef0cbf89a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json @@ -1,11 +1,11 @@ { "path": "\/name\/add", - "pathRegex": "#^\/name\/add$#s", + "pathRegex": "#PATH_REGEX#", "host": "localhost", - "hostRegex": "#^localhost$#si", + "hostRegex": "#HOST_REGEX#", "scheme": "http|https", "method": "PUT|POST", - "class": "Symfony\\Component\\Routing\\Route", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", "defaults": [], "requirements": "NO CUSTOM", "options": { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.md index 0a3f84be17c70..1d776c5ffe49e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.md @@ -1,10 +1,10 @@ - Path: /name/add -- Path Regex: #^/name/add$#s +- Path Regex: #PATH_REGEX# - Host: localhost -- Host Regex: #^localhost$#si +- Host Regex: #HOST_REGEX# - Scheme: http|https - Method: PUT|POST -- Class: Symfony\Component\Routing\Route +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub - Defaults: NONE - Requirements: NO CUSTOM - Options: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt index 560c474ae95c0..8e4e0cb009c3a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt @@ -1,10 +1,10 @@ Path /name/add -Path Regex #^/name/add$#s +Path Regex #PATH_REGEX# Host localhost -Host Regex #^localhost$#si +Host Regex #HOST_REGEX# Scheme http|https Method PUT|POST -Class Symfony\Component\Routing\Route +Class Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub Defaults NONE Requirements NO CUSTOM Options compiler_class: Symfony\Component\Routing\RouteCompiler diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.xml index 0f94cf7c41764..584ab1b12de59 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.xml @@ -1,7 +1,7 @@ - - /name/add - localhost + + /name/add + localhost http https PUT diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json index 350bffdb3a9c7..bd60070ed5cf4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json @@ -1,12 +1,12 @@ { "route_1": { "path": "\/hello\/{name}", - "pathRegex": "#^\/hello(?:\/(?P[a-z]+))?$#s", + "pathRegex": "#PATH_REGEX#", "host": "localhost", - "hostRegex": "#^localhost$#si", + "hostRegex": "#HOST_REGEX#", "scheme": "http|https", "method": "GET|HEAD", - "class": "Symfony\\Component\\Routing\\Route", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", "defaults": { "name": "Joseph" }, @@ -21,12 +21,12 @@ }, "route_2": { "path": "\/name\/add", - "pathRegex": "#^\/name\/add$#s", + "pathRegex": "#PATH_REGEX#", "host": "localhost", - "hostRegex": "#^localhost$#si", + "hostRegex": "#HOST_REGEX#", "scheme": "http|https", "method": "PUT|POST", - "class": "Symfony\\Component\\Routing\\Route", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", "defaults": [], "requirements": "NO CUSTOM", "options": { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md index 87efcc22e4718..f8b071d0ddac9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md @@ -2,12 +2,12 @@ route_1 ------- - Path: /hello/{name} -- Path Regex: #^/hello(?:/(?P[a-z]+))?$#s +- Path Regex: #PATH_REGEX# - Host: localhost -- Host Regex: #^localhost$#si +- Host Regex: #HOST_REGEX# - Scheme: http|https - Method: GET|HEAD -- Class: Symfony\Component\Routing\Route +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub - Defaults: - `name`: Joseph - Requirements: @@ -22,12 +22,12 @@ route_2 ------- - Path: /name/add -- Path Regex: #^/name/add$#s +- Path Regex: #PATH_REGEX# - Host: localhost -- Host Regex: #^localhost$#si +- Host Regex: #HOST_REGEX# - Scheme: http|https - Method: PUT|POST -- Class: Symfony\Component\Routing\Route +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub - Defaults: NONE - Requirements: NO CUSTOM - Options: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml index 6d17820c3143d..666a53730dee0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml @@ -1,8 +1,8 @@ - - /hello/{name} - localhost + + /hello/{name} + localhost http https GET @@ -19,9 +19,9 @@ - - /name/add - localhost + + /name/add + localhost http https PUT diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index ecbc96422989a..244e2a9c35788 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -177,7 +177,7 @@ private static function compilePattern(Route $route, $pattern, $isHost) return array( 'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', - 'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s'.($isHost ? 'i' : ''), + 'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''), 'tokens' => array_reverse($tokens), 'variables' => $variables, ); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index a87f063af57ac..5b0703cb7fb84 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -23,13 +23,13 @@ public function match($rawPathinfo) $request = $this->request ?: $this->createRequest($pathinfo); // foo - if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); } if (0 === strpos($pathinfo, '/bar')) { // bar - if (preg_match('#^/bar/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/bar/(?P[^/]++)$#sD', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { $allow = array_merge($allow, array('GET', 'HEAD')); goto not_bar; @@ -40,7 +40,7 @@ public function match($rawPathinfo) not_bar: // barhead - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P[^/]++)$#sD', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { $allow = array_merge($allow, array('GET', 'HEAD')); goto not_barhead; @@ -72,12 +72,12 @@ public function match($rawPathinfo) } // baz4 - if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); } // baz5 - if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { if ($this->context->getMethod() != 'POST') { $allow[] = 'POST'; goto not_baz5; @@ -88,7 +88,7 @@ public function match($rawPathinfo) not_baz5: // baz.baz6 - if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { if ($this->context->getMethod() != 'PUT') { $allow[] = 'PUT'; goto not_bazbaz6; @@ -106,7 +106,7 @@ public function match($rawPathinfo) } // quoter - if (preg_match('#^/(?P[\']+)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P[\']+)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); } @@ -118,30 +118,30 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/a')) { if (0 === strpos($pathinfo, '/a/b\'b')) { // foo1 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); } // bar1 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); } } // overridden - if (preg_match('#^/a/(?P.*)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/(?P.*)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); } if (0 === strpos($pathinfo, '/a/b\'b')) { // foo2 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); } // bar2 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); } @@ -151,7 +151,7 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/multi')) { // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); } @@ -168,12 +168,12 @@ public function match($rawPathinfo) } // foo3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); } // bar3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); } @@ -184,7 +184,7 @@ public function match($rawPathinfo) } // foo4 - if (preg_match('#^/aba/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); } @@ -192,7 +192,7 @@ public function match($rawPathinfo) $host = $this->context->getHost(); - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { // route1 if ('/route1' === $pathinfo) { return array('_route' => 'route1'); @@ -205,7 +205,7 @@ public function match($rawPathinfo) } - if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) { // route3 if ('/c2/route3' === $pathinfo) { return array('_route' => 'route3'); @@ -213,7 +213,7 @@ public function match($rawPathinfo) } - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { // route4 if ('/route4' === $pathinfo) { return array('_route' => 'route4'); @@ -221,7 +221,7 @@ public function match($rawPathinfo) } - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route5 if ('/route5' === $pathinfo) { return array('_route' => 'route5'); @@ -234,7 +234,7 @@ public function match($rawPathinfo) return array('_route' => 'route6'); } - if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) { if (0 === strpos($pathinfo, '/route1')) { // route11 if ('/route11' === $pathinfo) { @@ -247,12 +247,12 @@ public function match($rawPathinfo) } // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); } // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); } @@ -260,9 +260,9 @@ public function match($rawPathinfo) } - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route15 - if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); } @@ -270,7 +270,7 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/route1')) { // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); } @@ -289,12 +289,12 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/a/b')) { // b - if (preg_match('#^/a/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); } // c - if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index 7ec89b8e2f457..a7e7ce75be537 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -23,13 +23,13 @@ public function match($rawPathinfo) $request = $this->request ?: $this->createRequest($pathinfo); // foo - if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); } if (0 === strpos($pathinfo, '/bar')) { // bar - if (preg_match('#^/bar/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/bar/(?P[^/]++)$#sD', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { $allow = array_merge($allow, array('GET', 'HEAD')); goto not_bar; @@ -40,7 +40,7 @@ public function match($rawPathinfo) not_bar: // barhead - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P[^/]++)$#sD', $pathinfo, $matches)) { if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { $allow = array_merge($allow, array('GET', 'HEAD')); goto not_barhead; @@ -81,7 +81,7 @@ public function match($rawPathinfo) } // baz4 - if (preg_match('#^/test/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/?$#sD', $pathinfo, $matches)) { if ('/' === substr($pathinfo, -1)) { // no-op } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { @@ -95,7 +95,7 @@ public function match($rawPathinfo) not_baz4: // baz5 - if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { if ($this->context->getMethod() != 'POST') { $allow[] = 'POST'; goto not_baz5; @@ -106,7 +106,7 @@ public function match($rawPathinfo) not_baz5: // baz.baz6 - if (preg_match('#^/test/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { if ($this->context->getMethod() != 'PUT') { $allow[] = 'PUT'; goto not_bazbaz6; @@ -124,7 +124,7 @@ public function match($rawPathinfo) } // quoter - if (preg_match('#^/(?P[\']+)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P[\']+)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); } @@ -136,30 +136,30 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/a')) { if (0 === strpos($pathinfo, '/a/b\'b')) { // foo1 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); } // bar1 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); } } // overridden - if (preg_match('#^/a/(?P.*)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/(?P.*)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); } if (0 === strpos($pathinfo, '/a/b\'b')) { // foo2 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); } // bar2 - if (preg_match('#^/a/b\'b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); } @@ -169,7 +169,7 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/multi')) { // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); } @@ -195,12 +195,12 @@ public function match($rawPathinfo) } // foo3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); } // bar3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); } @@ -211,7 +211,7 @@ public function match($rawPathinfo) } // foo4 - if (preg_match('#^/aba/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); } @@ -219,7 +219,7 @@ public function match($rawPathinfo) $host = $this->context->getHost(); - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { // route1 if ('/route1' === $pathinfo) { return array('_route' => 'route1'); @@ -232,7 +232,7 @@ public function match($rawPathinfo) } - if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) { // route3 if ('/c2/route3' === $pathinfo) { return array('_route' => 'route3'); @@ -240,7 +240,7 @@ public function match($rawPathinfo) } - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { // route4 if ('/route4' === $pathinfo) { return array('_route' => 'route4'); @@ -248,7 +248,7 @@ public function match($rawPathinfo) } - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route5 if ('/route5' === $pathinfo) { return array('_route' => 'route5'); @@ -261,7 +261,7 @@ public function match($rawPathinfo) return array('_route' => 'route6'); } - if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) { if (0 === strpos($pathinfo, '/route1')) { // route11 if ('/route11' === $pathinfo) { @@ -274,12 +274,12 @@ public function match($rawPathinfo) } // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); } // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); } @@ -287,9 +287,9 @@ public function match($rawPathinfo) } - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { + if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route15 - if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); } @@ -297,7 +297,7 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/route1')) { // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); } @@ -316,12 +316,12 @@ public function match($rawPathinfo) if (0 === strpos($pathinfo, '/a/b')) { // b - if (preg_match('#^/a/b/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/a/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); } // c - if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index f5234dd43bbec..09b5876bc9580 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -29,7 +29,7 @@ public function match($rawPathinfo) } // dynamic - if (preg_match('#^/rootprefix/(?P[^/]++)$#s', $pathinfo, $matches)) { + if (preg_match('#^/rootprefix/(?P[^/]++)$#sD', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ()); } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index de79a073eaf0c..ab8fcd39c9dd4 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -162,6 +162,18 @@ public function testMatchSpecialRouteName() $this->assertEquals(array('_route' => '$péß^a|'), $matcher->match('/bar')); } + /** + * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException + */ + public function testTrailingEncodedNewlineIsNotOverlooked() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher->match('/foo%0a'); + } + public function testMatchNonAlpha() { $collection = new RouteCollection(); diff --git a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php index 8d89dae0f4a92..184eea048d17f 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php @@ -38,7 +38,7 @@ public function provideCompileData() array( 'Static route', array('/foo'), - '/foo', '#^/foo$#s', array(), array( + '/foo', '#^/foo$#sD', array(), array( array('text', '/foo'), ), ), @@ -46,7 +46,7 @@ public function provideCompileData() array( 'Route with a variable', array('/foo/{bar}'), - '/foo', '#^/foo/(?P[^/]++)$#s', array('bar'), array( + '/foo', '#^/foo/(?P[^/]++)$#sD', array('bar'), array( array('variable', '/', '[^/]++', 'bar'), array('text', '/foo'), ), @@ -55,7 +55,7 @@ public function provideCompileData() array( 'Route with a variable that has a default value', array('/foo/{bar}', array('bar' => 'bar')), - '/foo', '#^/foo(?:/(?P[^/]++))?$#s', array('bar'), array( + '/foo', '#^/foo(?:/(?P[^/]++))?$#sD', array('bar'), array( array('variable', '/', '[^/]++', 'bar'), array('text', '/foo'), ), @@ -64,7 +64,7 @@ public function provideCompileData() array( 'Route with several variables', array('/foo/{bar}/{foobar}'), - '/foo', '#^/foo/(?P[^/]++)/(?P[^/]++)$#s', array('bar', 'foobar'), array( + '/foo', '#^/foo/(?P[^/]++)/(?P[^/]++)$#sD', array('bar', 'foobar'), array( array('variable', '/', '[^/]++', 'foobar'), array('variable', '/', '[^/]++', 'bar'), array('text', '/foo'), @@ -74,7 +74,7 @@ public function provideCompileData() array( 'Route with several variables that have default values', array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')), - '/foo', '#^/foo(?:/(?P[^/]++)(?:/(?P[^/]++))?)?$#s', array('bar', 'foobar'), array( + '/foo', '#^/foo(?:/(?P[^/]++)(?:/(?P[^/]++))?)?$#sD', array('bar', 'foobar'), array( array('variable', '/', '[^/]++', 'foobar'), array('variable', '/', '[^/]++', 'bar'), array('text', '/foo'), @@ -84,7 +84,7 @@ public function provideCompileData() array( 'Route with several variables but some of them have no default values', array('/foo/{bar}/{foobar}', array('bar' => 'bar')), - '/foo', '#^/foo/(?P[^/]++)/(?P[^/]++)$#s', array('bar', 'foobar'), array( + '/foo', '#^/foo/(?P[^/]++)/(?P[^/]++)$#sD', array('bar', 'foobar'), array( array('variable', '/', '[^/]++', 'foobar'), array('variable', '/', '[^/]++', 'bar'), array('text', '/foo'), @@ -94,7 +94,7 @@ public function provideCompileData() array( 'Route with an optional variable as the first segment', array('/{bar}', array('bar' => 'bar')), - '', '#^/(?P[^/]++)?$#s', array('bar'), array( + '', '#^/(?P[^/]++)?$#sD', array('bar'), array( array('variable', '/', '[^/]++', 'bar'), ), ), @@ -102,7 +102,7 @@ public function provideCompileData() array( 'Route with a requirement of 0', array('/{bar}', array('bar' => null), array('bar' => '0')), - '', '#^/(?P0)?$#s', array('bar'), array( + '', '#^/(?P0)?$#sD', array('bar'), array( array('variable', '/', '0', 'bar'), ), ), @@ -110,7 +110,7 @@ public function provideCompileData() array( 'Route with an optional variable as the first segment with requirements', array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')), - '', '#^/(?P(foo|bar))?$#s', array('bar'), array( + '', '#^/(?P(foo|bar))?$#sD', array('bar'), array( array('variable', '/', '(foo|bar)', 'bar'), ), ), @@ -118,7 +118,7 @@ public function provideCompileData() array( 'Route with only optional variables', array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')), - '', '#^/(?P[^/]++)?(?:/(?P[^/]++))?$#s', array('foo', 'bar'), array( + '', '#^/(?P[^/]++)?(?:/(?P[^/]++))?$#sD', array('foo', 'bar'), array( array('variable', '/', '[^/]++', 'bar'), array('variable', '/', '[^/]++', 'foo'), ), @@ -127,7 +127,7 @@ public function provideCompileData() array( 'Route with a variable in last position', array('/foo-{bar}'), - '/foo', '#^/foo\-(?P[^/]++)$#s', array('bar'), array( + '/foo', '#^/foo\-(?P[^/]++)$#sD', array('bar'), array( array('variable', '-', '[^/]++', 'bar'), array('text', '/foo'), ), @@ -136,7 +136,7 @@ public function provideCompileData() array( 'Route with nested placeholders', array('/{static{var}static}'), - '/{static', '#^/\{static(?P[^/]+)static\}$#s', array('var'), array( + '/{static', '#^/\{static(?P[^/]+)static\}$#sD', array('var'), array( array('text', 'static}'), array('variable', '', '[^/]+', 'var'), array('text', '/{static'), @@ -146,7 +146,7 @@ public function provideCompileData() array( 'Route without separator between variables', array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')), - '', '#^/(?P[^/\.]+)(?P[^/\.]+)(?P(y|Y))(?:(?P[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array( + '', '#^/(?P[^/\.]+)(?P[^/\.]+)(?P(y|Y))(?:(?P[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#sD', array('w', 'x', 'y', 'z', '_format'), array( array('variable', '.', '[^/]++', '_format'), array('variable', '', '[^/\.]++', 'z'), array('variable', '', '(y|Y)', 'y'), @@ -158,7 +158,7 @@ public function provideCompileData() array( 'Route with a format', array('/foo/{bar}.{_format}'), - '/foo', '#^/foo/(?P[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array( + '/foo', '#^/foo/(?P[^/\.]++)\.(?P<_format>[^/]++)$#sD', array('bar', '_format'), array( array('variable', '.', '[^/]++', '_format'), array('variable', '/', '[^/\.]++', 'bar'), array('text', '/foo'), @@ -221,21 +221,21 @@ public function provideCompileWithHostData() array( 'Route with host pattern', array('/hello', array(), array(), array(), 'www.example.com'), - '/hello', '#^/hello$#s', array(), array(), array( + '/hello', '#^/hello$#sD', array(), array(), array( array('text', '/hello'), ), - '#^www\.example\.com$#si', array(), array( + '#^www\.example\.com$#sDi', array(), array( array('text', 'www.example.com'), ), ), array( 'Route with host pattern and some variables', array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'), - '/hello', '#^/hello/(?P[^/]++)$#s', array('tld', 'name'), array('name'), array( + '/hello', '#^/hello/(?P[^/]++)$#sD', array('tld', 'name'), array('name'), array( array('variable', '/', '[^/]++', 'name'), array('text', '/hello'), ), - '#^www\.example\.(?P[^\.]++)$#si', array('tld'), array( + '#^www\.example\.(?P[^\.]++)$#sDi', array('tld'), array( array('variable', '.', '[^\.]++', 'tld'), array('text', 'www.example'), ), @@ -243,10 +243,10 @@ public function provideCompileWithHostData() array( 'Route with variable at beginning of host', array('/hello', array(), array(), array(), '{locale}.example.{tld}'), - '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( + '/hello', '#^/hello$#sD', array('locale', 'tld'), array(), array( array('text', '/hello'), ), - '#^(?P[^\.]++)\.example\.(?P[^\.]++)$#si', array('locale', 'tld'), array( + '#^(?P[^\.]++)\.example\.(?P[^\.]++)$#sDi', array('locale', 'tld'), array( array('variable', '.', '[^\.]++', 'tld'), array('text', '.example'), array('variable', '', '[^\.]++', 'locale'), @@ -255,10 +255,10 @@ public function provideCompileWithHostData() array( 'Route with host variables that has a default value', array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'), - '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( + '/hello', '#^/hello$#sD', array('locale', 'tld'), array(), array( array('text', '/hello'), ), - '#^(?P[^\.]++)\.example\.(?P[^\.]++)$#si', array('locale', 'tld'), array( + '#^(?P[^\.]++)\.example\.(?P[^\.]++)$#sDi', array('locale', 'tld'), array( array('variable', '.', '[^\.]++', 'tld'), array('text', '.example'), array('variable', '', '[^\.]++', 'locale'), diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index 18c0206474a34..edaf3b8cfddf3 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -272,7 +272,7 @@ public function testSerializeWhenCompiled() */ public function testSerializedRepresentationKeepsWorking() { - $serialized = 'C:31:"Symfony\Component\Routing\Route":934:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":569:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:39:"#^(?P[^\.]++)\.example\.net$#si";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}'; + $serialized = 'C:31:"Symfony\Component\Routing\Route":936:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":571:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:31:"#^/prefix(?:/(?P\d+))?$#sD";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:40:"#^(?P[^\.]++)\.example\.net$#sDi";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}'; $unserialized = unserialize($serialized); $route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+')); From 3a470c4ecf25f921a36a549bca3205bb5d1cba77 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 4 Feb 2018 17:22:42 +0100 Subject: [PATCH 23/68] [Process] Check PHP_BINDIR before $PATH in PhpExecutableFinder --- src/Symfony/Component/Process/PhpExecutableFinder.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index fb297825fe364..25415eda793bd 100644 --- a/src/Symfony/Component/Process/PhpExecutableFinder.php +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -62,6 +62,10 @@ public function find($includeArgs = true) } } + if (is_executable($php = PHP_BINDIR.'/php'.('\\' === DIRECTORY_SEPARATOR ? '.exe' : ''))) { + return $php; + } + $dirs = array(PHP_BINDIR); if ('\\' === DIRECTORY_SEPARATOR) { $dirs[] = 'C:\xampp\php\\'; From f167b505c427625fc283a1720be76a83262ae9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 5 Feb 2018 08:51:00 +0100 Subject: [PATCH 24/68] [DI] minor: use a strict comparision in setDecoratedService --- src/Symfony/Component/DependencyInjection/Definition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 6f2a3c7e82a7f..8286e9d1e70cd 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -144,7 +144,7 @@ public function setFactoryMethod($factoryMethod) */ public function setDecoratedService($id, $renamedId = null) { - if ($renamedId && $id == $renamedId) { + if ($renamedId && $id === $renamedId) { throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); } From 899ead2b66639c8fdc49c2ce1e1e80424a27943d Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 6 Feb 2018 07:47:25 -0200 Subject: [PATCH 25/68] Fix misspelling variable --- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 5dad4057612d0..96f87958ed9c5 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1982,11 +1982,11 @@ public function testMethodSafeChecksCacheable() /** * @dataProvider methodCacheableProvider */ - public function testMethodCacheable($method, $chacheable) + public function testMethodCacheable($method, $cacheable) { $request = new Request(); $request->setMethod($method); - $this->assertEquals($chacheable, $request->isMethodCacheable()); + $this->assertEquals($cacheable, $request->isMethodCacheable()); } public function methodCacheableProvider() From dab422287fa0f2b89a95c2d705969081fe6c76b3 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 7 Feb 2018 21:12:42 +0100 Subject: [PATCH 26/68] do not mock the container builder in tests --- .../Compiler/AddCacheWarmerPassTest.php | 70 ++++------- .../AddConstraintValidatorsPassTest.php | 72 ++++-------- .../LegacyFragmentRendererPassTest.php | 63 ++-------- .../Compiler/LoggingTranslatorPassTest.php | 73 ++++-------- .../Compiler/ProfilerPassTest.php | 63 +++------- .../Compiler/SerializerPassTest.php | 85 +++++--------- .../Compiler/TranslatorPassTest.php | 35 +++--- .../ConstraintValidatorFactoryTest.php | 38 +++--- .../Compiler/TwigLoaderPassTest.php | 100 ++++------------ .../Compiler/ExtensionCompilerPassTest.php | 58 ++++++--- .../Tests/Extension/ExtensionTest.php | 56 +++------ .../RegisterListenersPassTest.php | 61 ++-------- .../FragmentRendererPassTest.php | 110 ++++-------------- .../MergeExtensionConfigurationPassTest.php | 59 +++++----- 14 files changed, 289 insertions(+), 654 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php index 330deae6463d7..e58ed97724481 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; @@ -19,73 +20,44 @@ class AddCacheWarmerPassTest extends TestCase { public function testThatCacheWarmersAreProcessedInPriorityOrder() { - $services = array( - 'my_cache_warmer_service1' => array(0 => array('priority' => 100)), - 'my_cache_warmer_service2' => array(0 => array('priority' => 200)), - 'my_cache_warmer_service3' => array(), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock(); + $container = new ContainerBuilder(); + $cacheWarmerDefinition = $container->register('cache_warmer')->addArgument(array()); + $container->register('my_cache_warmer_service1')->addTag('kernel.cache_warmer', array('priority' => 100)); + $container->register('my_cache_warmer_service2')->addTag('kernel.cache_warmer', array('priority' => 200)); + $container->register('my_cache_warmer_service3')->addTag('kernel.cache_warmer'); - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - $container->expects($this->atLeastOnce()) - ->method('getDefinition') - ->with('cache_warmer') - ->will($this->returnValue($definition)); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(true)); + $addCacheWarmerPass = new AddCacheWarmerPass(); + $addCacheWarmerPass->process($container); - $definition->expects($this->once()) - ->method('replaceArgument') - ->with(0, array( + $this->assertEquals( + array( new Reference('my_cache_warmer_service2'), new Reference('my_cache_warmer_service1'), new Reference('my_cache_warmer_service3'), - )); - - $addCacheWarmerPass = new AddCacheWarmerPass(); - $addCacheWarmerPass->process($container); + ), + $cacheWarmerDefinition->getArgument(0) + ); } public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); + $container = new ContainerBuilder(); $addCacheWarmerPass = new AddCacheWarmerPass(); $addCacheWarmerPass->process($container); + + // we just check that the pass does not break if no cache warmer is registered + $this->addToAssertionCount(1); } public function testThatCacheWarmersMightBeNotDefined() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array())); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(true)); - - $definition->expects($this->never())->method('replaceArgument'); + $container = new ContainerBuilder(); + $cacheWarmerDefinition = $container->register('cache_warmer')->addArgument(array()); $addCacheWarmerPass = new AddCacheWarmerPass(); $addCacheWarmerPass->process($container); + + $this->assertSame(array(), $cacheWarmerDefinition->getArgument(0)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php index e58068900fc8f..0be1f77d5189e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php @@ -13,72 +13,40 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; class AddConstraintValidatorsPassTest extends TestCase { public function testThatConstraintValidatorServicesAreProcessed() { - $services = array( - 'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')), - 'my_constraint_validator_service2' => array(), - ); - - $validatorFactoryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock(); - - $validatorDefinition1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock(); - $validatorDefinition2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock(); - - $validatorDefinition1->expects($this->atLeastOnce()) - ->method('getClass') - ->willReturn('My\Fully\Qualified\Class\Named\Validator1'); - $validatorDefinition2->expects($this->atLeastOnce()) - ->method('getClass') - ->willReturn('My\Fully\Qualified\Class\Named\Validator2'); + $container = new ContainerBuilder(); + $constraintValidatorFactoryDefinition = $container->register('validator.validator_factory') + ->setArguments(array(new Reference('service_container'), array())); + $container->register('my_constraint_validator_service1', 'My\Fully\Qualified\Class\Named\Validator1') + ->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1')); + $container->register('my_constraint_validator_service2', 'My\Fully\Qualified\Class\Named\Validator2') + ->addTag('validator.constraint_validator'); - $container->expects($this->any()) - ->method('getDefinition') - ->with($this->anything()) - ->will($this->returnValueMap(array( - array('my_constraint_validator_service1', $validatorDefinition1), - array('my_constraint_validator_service2', $validatorDefinition2), - array('validator.validator_factory', $validatorFactoryDefinition), - ))); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('validator.validator_factory') - ->will($this->returnValue(true)); + $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); + $addConstraintValidatorsPass->process($container); - $validatorFactoryDefinition->expects($this->once()) - ->method('replaceArgument') - ->with(1, array( + $this->assertEquals( + array( 'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1', 'my_constraint_validator_alias1' => 'my_constraint_validator_service1', 'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2', - )); - - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); + ), + $constraintValidatorFactoryDefinition->getArgument(1) + ); } public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('validator.validator_factory') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); + $addConstraintValidatorsPass->process(new ContainerBuilder()); + + // we just check that the pass does not fail if no constraint validator factory is registered + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php index d4f75ee95c204..b275047939062 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass; @@ -29,29 +30,10 @@ class LegacyFragmentRendererPassTest extends TestCase */ public function testContentRendererWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_content_renderer' => array(), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('stdClass')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'stdClass') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); @@ -59,38 +41,15 @@ public function testContentRendererWithoutInterface() public function testValidContentRenderer() { - $services = array( - 'my_content_renderer' => array(), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRenderer', array(new Reference('my_content_renderer'))) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RendererService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RendererService') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRenderer', array(new Reference('my_content_renderer')))), $fragmentHandlerDefinition->getMethodCalls()); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php index db6557913b06e..00da2724d14f2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php @@ -13,75 +13,52 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; class LoggingTranslatorPassTest extends TestCase { public function testProcess() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $parameterBag = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface')->getMock(); - - $container->expects($this->exactly(2)) - ->method('hasAlias') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('getParameter') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('getAlias') - ->will($this->returnValue('translation.default')); - - $container->expects($this->exactly(3)) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $container->expects($this->once()) - ->method('hasParameter') - ->with('translator.logging') - ->will($this->returnValue(true)); - - $definition->expects($this->once()) - ->method('getClass') - ->will($this->returnValue('%translator.class%')); - - $parameterBag->expects($this->once()) - ->method('resolveValue') - ->will($this->returnValue("Symfony\Bundle\FrameworkBundle\Translation\Translator")); - - $container->expects($this->once()) - ->method('getParameterBag') - ->will($this->returnValue($parameterBag)); + $container = new ContainerBuilder(); + $container->setParameter('translator.logging', true); + $container->setParameter('translator.class', 'Symfony\Component\Translation\Translator'); + $container->register('monolog.logger'); + $container->setAlias('logger', 'monolog.logger'); + $container->register('translator.default', '%translator.class%'); + $container->register('translator.logging', '%translator.class%'); + $container->setAlias('translator', 'translator.default'); + $translationWarmerDefinition = $container->register('translation.warmer')->addArgument(new Reference('translator')); $pass = new LoggingTranslatorPass(); $pass->process($container); + + $this->assertEquals(new Reference('translator.logging.inner'), $translationWarmerDefinition->getArgument(0)); } public function testThatCompilerPassIsIgnoredIfThereIsNotLoggerDefinition() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $container->expects($this->once()) - ->method('hasAlias') - ->will($this->returnValue(false)); + $container = new ContainerBuilder(); + $container->register('identity_translator'); + $container->setAlias('translator', 'identity_translator'); $pass = new LoggingTranslatorPass(); $pass->process($container); + + // we just check that the compiler pass does not break if a logger is not registered + $this->addToAssertionCount(1); } public function testThatCompilerPassIsIgnoredIfThereIsNotTranslatorDefinition() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $container->expects($this->at(0)) - ->method('hasAlias') - ->will($this->returnValue(true)); - - $container->expects($this->at(0)) - ->method('hasAlias') - ->will($this->returnValue(false)); + $container = new ContainerBuilder(); + $container->register('monolog.logger'); + $container->setAlias('logger', 'monolog.logger'); $pass = new LoggingTranslatorPass(); $pass->process($container); + + // we just check that the compiler pass does not break if a translator is not registered + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php index e064ce9f17f02..9fcae720b20b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -12,18 +12,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; class ProfilerPassTest extends TestCase { - private $profilerDefinition; - - protected function setUp() - { - $this->profilerDefinition = new Definition('ProfilerClass'); - } - /** * Tests that collectors that specify a template but no "id" will throw * an exception (both are needed if the template is specified). @@ -31,17 +24,15 @@ protected function setUp() * Thus, a fully-valid tag looks something like this: * * + * + * @expectedException \InvalidArgumentException */ public function testTemplateNoIdThrowsException() { - // one service, with a template key, but no id - $services = array( - 'my_collector_service' => array(0 => array('template' => 'foo')), - ); - - $builder = $this->createContainerMock($services); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); + $builder = new ContainerBuilder(); + $builder->register('profiler', 'ProfilerClass'); + $builder->register('my_collector_service') + ->addTag('data_collector', array('template' => 'foo')); $profilerPass = new ProfilerPass(); $profilerPass->process($builder); @@ -49,45 +40,19 @@ public function testTemplateNoIdThrowsException() public function testValidCollector() { - // one service, with a template key, but no id - $services = array( - 'my_collector_service' => array(0 => array('template' => 'foo', 'id' => 'my_collector')), - ); - - $container = $this->createContainerMock($services); - - // fake the getDefinition() to return a Profiler definition - $container->expects($this->atLeastOnce()) - ->method('getDefinition'); - - // assert that the data_collector.templates parameter should be set - $container->expects($this->once()) - ->method('setParameter') - ->with('data_collector.templates', array('my_collector_service' => array('my_collector', 'foo'))); + $container = new ContainerBuilder(); + $profilerDefinition = $container->register('profiler', 'ProfilerClass'); + $container->register('my_collector_service') + ->addTag('data_collector', array('template' => 'foo', 'id' => 'my_collector')); $profilerPass = new ProfilerPass(); $profilerPass->process($container); + $this->assertSame(array('my_collector_service' => array('my_collector', 'foo')), $container->getParameter('data_collector.templates')); + // grab the method calls off of the "profiler" definition - $methodCalls = $this->profilerDefinition->getMethodCalls(); + $methodCalls = $profilerDefinition->getMethodCalls(); $this->assertCount(1, $methodCalls); $this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call } - - private function createContainerMock($services) - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter'))->getMock(); - $container->expects($this->any()) - ->method('hasDefinition') - ->with($this->equalTo('profiler')) - ->will($this->returnValue(true)); - $container->expects($this->any()) - ->method('getDefinition') - ->will($this->returnValue($this->profilerDefinition)); - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - return $container; - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php index 6fa27be17a3db..12e9e1c34bbb7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; @@ -22,48 +23,30 @@ */ class SerializerPassTest extends TestCase { + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage You must tag at least one service as "serializer.normalizer" to use the Serializer service + */ public function testThrowExceptionWhenNoNormalizers() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('serializer.normalizer') - ->will($this->returnValue(array())); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); + $container = new ContainerBuilder(); + $container->register('serializer'); $serializerPass = new SerializerPass(); $serializerPass->process($container); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage You must tag at least one service as "serializer.encoder" to use the Serializer service + */ public function testThrowExceptionWhenNoEncoders() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->any()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls( - array('n' => array('serializer.normalizer')), - array() - )); - - $container->expects($this->once()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); + $container = new ContainerBuilder(); + $container->register('serializer') + ->addArgument(array()) + ->addArgument(array()); + $container->register('normalizer')->addTag('serializer.normalizer'); $serializerPass = new SerializerPass(); $serializerPass->process($container); @@ -71,34 +54,18 @@ public function testThrowExceptionWhenNoEncoders() public function testServicesAreOrderedAccordingToPriority() { - $services = array( - 'n3' => array(array()), - 'n1' => array(array('priority' => 200)), - 'n2' => array(array('priority' => 100)), - ); - - $expected = array( - new Reference('n1'), - new Reference('n2'), - new Reference('n3'), - ); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); + $container = new ContainerBuilder(); + $serializerDefinition = $container->register('serializer') + ->addArgument(array()) + ->addArgument(array()); + $container->register('normalizer3')->addTag('serializer.normalizer'); + $container->register('normalizer1')->addTag('serializer.normalizer', array('priority' => 200)); + $container->register('normalizer2')->addTag('serializer.normalizer', array('priority' => 100)); + $container->register('encoder')->addTag('serializer.encoder'); $serializerPass = new SerializerPass(); + $serializerPass->process($container); - $method = new \ReflectionMethod( - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass', - 'findAndSortTaggedServices' - ); - $method->setAccessible(true); - - $actual = $method->invoke($serializerPass, 'tag', $container); - - $this->assertEquals($expected, $actual); + $this->assertEquals(array(new Reference('normalizer1'), new Reference('normalizer2'), new Reference('normalizer3')), $serializerDefinition->getArgument(0)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php index 10a38aabdb402..e176c7534a343 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; @@ -19,28 +20,22 @@ class TranslatorPassTest extends TestCase { public function testValidCollector() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->at(0)) - ->method('addMethodCall') - ->with('addLoader', array('xliff', new Reference('xliff'))); - $definition->expects($this->at(1)) - ->method('addMethodCall') - ->with('addLoader', array('xlf', new Reference('xliff'))); + $container = new ContainerBuilder(); + $container->register('translator.default') + ->setArguments(array(null, null, array())); + $translationLoaderDefinition = $container->register('translation.loader'); + $container->register('xliff') + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition'))->getMock(); - $container->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - $container->expects($this->once()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - $container->expects($this->once()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf'))))); - $container->expects($this->once()) - ->method('findDefinition') - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock())); $pass = new TranslatorPass(); $pass->process($container); + + $this->assertEquals( + array( + array('addLoader', array('xliff', new Reference('xliff'))), + array('addLoader', array('xlf', new Reference('xliff'))), + ), + $translationLoaderDefinition->getMethodCalls() + ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php index 6cf9574ece96b..995048455f7b2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php @@ -14,7 +14,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Blank as BlankConstraint; +use Symfony\Component\Validator\ConstraintValidator; class ConstraintValidatorFactoryTest extends TestCase { @@ -42,26 +44,13 @@ public function testGetInstanceReturnsExistingValidator() public function testGetInstanceReturnsService() { - $service = 'validator_constraint_service'; - $alias = 'validator_constraint_alias'; - $validator = $this->getMockForAbstractClass('Symfony\\Component\\Validator\\ConstraintValidator'); + $validator = new DummyConstraintValidator(); - // mock ContainerBuilder b/c it implements TaggedContainerInterface - $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('get'))->getMock(); - $container - ->expects($this->once()) - ->method('get') - ->with($service) - ->will($this->returnValue($validator)); - - $constraint = $this->getMockBuilder('Symfony\\Component\\Validator\\Constraint')->getMock(); - $constraint - ->expects($this->once()) - ->method('validatedBy') - ->will($this->returnValue($alias)); + $container = new Container(); + $container->set('validator_constraint_service', $validator); $factory = new ConstraintValidatorFactory($container, array('validator_constraint_alias' => 'validator_constraint_service')); - $this->assertSame($validator, $factory->getInstance($constraint)); + $this->assertSame($validator, $factory->getInstance(new ConstraintStub())); } /** @@ -79,3 +68,18 @@ public function testGetInstanceInvalidValidatorClass() $factory->getInstance($constraint); } } + +class ConstraintStub extends Constraint +{ + public function validatedBy() + { + return 'validator_constraint_alias'; + } +} + +class DummyConstraintValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php index 10bcf3e8f66a8..b7870ac56c06e 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php @@ -12,13 +12,14 @@ namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigLoaderPass; class TwigLoaderPassTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ContainerBuilder */ private $builder; /** @@ -32,62 +33,33 @@ class TwigLoaderPassTest extends TestCase protected function setUp() { - $this->builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'setAlias', 'getDefinition'))->getMock(); + $this->builder = new ContainerBuilder(); + $this->builder->register('twig'); $this->chainLoader = new Definition('loader'); $this->pass = new TwigLoaderPass(); } - public function testMapperPassWithOneTaggedLoaders() + public function testMapperPassWithOneTaggedLoader() { - $serviceIds = array( - 'test_loader_1' => array( - array(), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'test_loader_1'); + $this->builder->register('test_loader_1') + ->addTag('twig.loader'); $this->pass->process($this->builder); + + $this->assertSame('test_loader_1', (string) $this->builder->getAlias('twig.loader')); } public function testMapperPassWithTwoTaggedLoaders() { - $serviceIds = array( - 'test_loader_1' => array( - array(), - ), - 'test_loader_2' => array( - array(), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('getDefinition') - ->with('twig.loader.chain') - ->will($this->returnValue($this->chainLoader)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + $this->builder->setDefinition('twig.loader.chain', $this->chainLoader); + $this->builder->register('test_loader_1') + ->addTag('twig.loader'); + $this->builder->register('test_loader_2') + ->addTag('twig.loader'); $this->pass->process($this->builder); + + $this->assertSame('twig.loader.chain', (string) $this->builder->getAlias('twig.loader')); $calls = $this->chainLoader->getMethodCalls(); $this->assertCount(2, $calls); $this->assertEquals('addLoader', $calls[0][0]); @@ -98,32 +70,15 @@ public function testMapperPassWithTwoTaggedLoaders() public function testMapperPassWithTwoTaggedLoadersWithPriority() { - $serviceIds = array( - 'test_loader_1' => array( - array('priority' => 100), - ), - 'test_loader_2' => array( - array('priority' => 200), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('getDefinition') - ->with('twig.loader.chain') - ->will($this->returnValue($this->chainLoader)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + $this->builder->setDefinition('twig.loader.chain', $this->chainLoader); + $this->builder->register('test_loader_1') + ->addTag('twig.loader', array('priority' => 100)); + $this->builder->register('test_loader_2') + ->addTag('twig.loader', array('priority' => 200)); $this->pass->process($this->builder); + + $this->assertSame('twig.loader.chain', (string) $this->builder->getAlias('twig.loader')); $calls = $this->chainLoader->getMethodCalls(); $this->assertCount(2, $calls); $this->assertEquals('addLoader', $calls[0][0]); @@ -137,15 +92,6 @@ public function testMapperPassWithTwoTaggedLoadersWithPriority() */ public function testMapperPassWithZeroTaggedLoaders() { - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue(array())); - $this->pass->process($this->builder); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php index e083611458770..f4c4353abe9ed 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php @@ -12,7 +12,10 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ExtensionCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; /** * @author Wouter J @@ -24,33 +27,52 @@ class ExtensionCompilerPassTest extends TestCase protected function setUp() { - $this->container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); + $this->container = new ContainerBuilder(); $this->pass = new ExtensionCompilerPass(); } public function testProcess() { - $extension1 = $this->createExtensionMock(true); - $extension1->expects($this->once())->method('process'); - $extension2 = $this->createExtensionMock(false); - $extension3 = $this->createExtensionMock(false); - $extension4 = $this->createExtensionMock(true); - $extension4->expects($this->once())->method('process'); - - $this->container->expects($this->any()) - ->method('getExtensions') - ->will($this->returnValue(array($extension1, $extension2, $extension3, $extension4))) - ; + $extension1 = new CompilerPassExtension('extension1'); + $extension2 = new DummyExtension('extension2'); + $extension3 = new DummyExtension('extension3'); + $extension4 = new CompilerPassExtension('extension4'); + + $this->container->registerExtension($extension1); + $this->container->registerExtension($extension2); + $this->container->registerExtension($extension3); + $this->container->registerExtension($extension4); $this->pass->process($this->container); + + $this->assertCount(2, $this->container->getDefinitions()); } +} + +class DummyExtension extends Extension +{ + private $alias; - private function createExtensionMock($hasInlineCompile) + public function __construct($alias) { - return $this->getMockBuilder('Symfony\Component\DependencyInjection\\'.( - $hasInlineCompile - ? 'Compiler\CompilerPassInterface' - : 'Extension\ExtensionInterface' - ))->getMock(); + $this->alias = $alias; } + + public function getAlias() + { + return $this->alias; + } + + public function load(array $configs, ContainerBuilder $container) + { + } + + public function process(ContainerBuilder $container) + { + $container->register($this->alias); + } +} + +class CompilerPassExtension extends DummyExtension implements CompilerPassInterface +{ } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php b/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php index 90852c359e514..9f66bfd7c6802 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\DependencyInjection\Tests\Extension; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; class ExtensionTest extends TestCase { @@ -20,36 +22,8 @@ class ExtensionTest extends TestCase */ public function testIsConfigEnabledReturnsTheResolvedValue($enabled) { - $pb = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBag') - ->setMethods(array('resolveValue')) - ->getMock() - ; - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') - ->setMethods(array('getParameterBag')) - ->getMock() - ; - - $pb->expects($this->once()) - ->method('resolveValue') - ->with($this->equalTo($enabled)) - ->will($this->returnValue($enabled)) - ; - - $container->expects($this->once()) - ->method('getParameterBag') - ->will($this->returnValue($pb)) - ; - - $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') - ->setMethods(array()) - ->getMockForAbstractClass() - ; - - $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); - $r->setAccessible(true); - - $r->invoke($extension, $container, array('enabled' => $enabled)); + $extension = new EnableableExtension(); + $this->assertSame($enabled, $extension->isConfigEnabled(new ContainerBuilder(), array('enabled' => $enabled))); } public function getResolvedEnabledFixtures() @@ -66,18 +40,20 @@ public function getResolvedEnabledFixtures() */ public function testIsConfigEnabledOnNonEnableableConfig() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') - ->getMock() - ; + $extension = new EnableableExtension(); - $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') - ->setMethods(array()) - ->getMockForAbstractClass() - ; + $extension->isConfigEnabled(new ContainerBuilder(), array()); + } +} - $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); - $r->setAccessible(true); +class EnableableExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } - $r->invoke($extension, $container, array()); + public function isConfigEnabled(ContainerBuilder $container, array $config) + { + return parent::isConfigEnabled($container, $config); } } diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index 53d7282b37a7a..7490d0d25fda8 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -25,32 +25,10 @@ class RegisterListenersPassTest extends TestCase */ public function testEventSubscriberWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_event_subscriber' => array(0 => array()), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('stdClass')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'stdClass') + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); @@ -62,34 +40,15 @@ public function testValidEventSubscriber() 'my_event_subscriber' => array(0 => array()), ); - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $builder->expects($this->atLeastOnce()) - ->method('findDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $eventDispatcherDefinition = $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService') + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); + + $this->assertEquals(array(array('addSubscriberService', array('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'))), $eventDispatcherDefinition->getMethodCalls()); } /** diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php index 2a27fcac21461..8bac207d176cd 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; @@ -24,118 +25,47 @@ class FragmentRendererPassTest extends TestCase */ public function testLegacyFragmentRedererWithoutAlias() { - // no alias - $services = array( - 'my_content_renderer' => array(array()), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRenderer', array(new Reference('my_content_renderer'))) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService')); - $definition - ->expects($this->once()) - ->method('isPublic') - ->will($this->returnValue(true)) - ; - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRenderer', array(new Reference('my_content_renderer')))), $fragmentHandlerDefinition->getMethodCalls()); } /** * Tests that content rendering not implementing FragmentRendererInterface - * trigger an exception. + * triggers an exception. * * @expectedException \InvalidArgumentException */ public function testContentRendererWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\DependencyInjection\Definition') + ->addTag('kernel.fragment_renderer', array('alias' => 'foo')); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRendererService', array('foo', 'my_content_renderer'))), $fragmentHandlerDefinition->getMethodCalls()); } public function testValidContentRenderer() { - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRendererService', array('foo', 'my_content_renderer')) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService')); - $definition - ->expects($this->once()) - ->method('isPublic') - ->will($this->returnValue(true)) - ; - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') + ->addTag('kernel.fragment_renderer', array('alias' => 'foo')); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRendererService', array('foo', 'my_content_renderer'))), $fragmentHandlerDefinition->getMethodCalls()); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php index 81fc8b455d183..ae421d919bfd8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -12,44 +12,39 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class MergeExtensionConfigurationPassTest extends TestCase { public function testAutoloadMainExtension() { - $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('getExtensionConfig', 'loadFromExtension', 'getParameterBag', 'getDefinitions', 'getAliases', 'getExtensions'))->getMock(); - $params = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag')->getMock(); - - $container->expects($this->at(0)) - ->method('getExtensionConfig') - ->with('loaded') - ->will($this->returnValue(array(array()))); - $container->expects($this->at(1)) - ->method('getExtensionConfig') - ->with('notloaded') - ->will($this->returnValue(array())); - $container->expects($this->once()) - ->method('loadFromExtension') - ->with('notloaded', array()); - - $container->expects($this->any()) - ->method('getParameterBag') - ->will($this->returnValue($params)); - $params->expects($this->any()) - ->method('all') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getDefinitions') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getAliases') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getExtensions') - ->will($this->returnValue(array())); - - $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); + $container = new ContainerBuilder(); + $container->registerExtension(new LoadedExtension()); + $container->registerExtension(new NotLoadedExtension()); + $container->loadFromExtension('loaded', array()); + + $configPass = new MergeExtensionConfigurationPass(array('loaded', 'not_loaded')); $configPass->process($container); + + $this->assertTrue($container->hasDefinition('loaded.foo')); + $this->assertTrue($container->hasDefinition('not_loaded.bar')); + } +} + +class LoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('loaded.foo'); + } +} + +class NotLoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('not_loaded.bar'); } } From a9ab167abfda01b46c1d77a2d85078f860998046 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 9 Feb 2018 08:49:27 +0100 Subject: [PATCH 27/68] backport regression test from 3.4 --- .../Tests/Extractors/PhpDocExtractorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index 6477ba1967721..4110c6b8a5bf4 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -74,4 +74,21 @@ public function typesProvider() array('staticSetter', null, null, null), ); } + + public function testParamTagTypeIsOmitted() + { + $this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\PhpDocExtractors\OmittedParamTagTypeDocBlock', 'omittedType')); + } +} + +class OmittedParamTagTypeDocBlock +{ + /** + * The type is omitted here to ensure that the extractor doesn't choke on missing types. + * + * @param $omittedTagType + */ + public function setOmittedType(array $omittedTagType) + { + } } From 51d9008d682c09a594bda0a8e38652ec9b820ce8 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Fri, 9 Feb 2018 13:42:37 +0100 Subject: [PATCH 28/68] [Security] fix merge of 2.7 into 2.8 + add test case --- .../UsernamePasswordFormAuthenticationListener.php | 10 +++++++--- ...ernamePasswordFormAuthenticationListenerTest.php | 13 +++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index d7802c76d2166..f8466278da63b 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -96,9 +96,13 @@ protected function attemptAuthentication(Request $request) } } - $requestBag = $this->options['post_only'] ? $request->request : $request; - $username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']); - $password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']); + if ($this->options['post_only']) { + $username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']); + $password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']); + } else { + $username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']); + $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); + } if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username))); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 2e99f70e7e26b..106740e56fe3c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -77,10 +77,11 @@ public function testHandleWhenUsernameLength($username, $ok) } /** + * @dataProvider postOnlyDataProvider * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * @expectedExceptionMessage The key "_username" must be a string, "array" given. */ - public function testHandleNonStringUsername() + public function testHandleNonStringUsername($postOnly) { $request = Request::create('/login_check', 'POST', array('_username' => array())); $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); @@ -93,7 +94,7 @@ public function testHandleNonStringUsername() 'foo', new DefaultAuthenticationSuccessHandler($httpUtils), new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), - array('require_previous_session' => false) + array('require_previous_session' => false, 'post_only' => $postOnly) ); $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); @@ -101,6 +102,14 @@ public function testHandleNonStringUsername() $listener->handle($event); } + public function postOnlyDataProvider() + { + return array( + array(true), + array(false), + ); + } + public function getUsernameForLength() { return array( From d195a6f0600fdfb0665f4a7844dc32646f73b1ab Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Feb 2018 13:55:03 +0100 Subject: [PATCH 29/68] [SecurityBundle] Backport test --- ...amePasswordFormAuthenticationListenerTest.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 2e99f70e7e26b..8634eca017386 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -77,14 +77,14 @@ public function testHandleWhenUsernameLength($username, $ok) } /** + * @dataProvider postOnlyDataProvider * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * @expectedExceptionMessage The key "_username" must be a string, "array" given. */ - public function testHandleNonStringUsername() + public function testHandleNonStringUsername($postOnly) { $request = Request::create('/login_check', 'POST', array('_username' => array())); $request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock()); - $listener = new UsernamePasswordFormAuthenticationListener( new TokenStorage(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), @@ -93,14 +93,20 @@ public function testHandleNonStringUsername() 'foo', new DefaultAuthenticationSuccessHandler($httpUtils), new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils), - array('require_previous_session' => false) + array('require_previous_session' => false, 'post_only' => $postOnly) ); - $event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); - $listener->handle($event); } + public function postOnlyDataProvider() + { + return array( + array(true), + array(false), + ); + } + public function getUsernameForLength() { return array( From e88e1ff494f9fdd3a91407993d8b4a918698c340 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Sat, 10 Feb 2018 18:16:30 +0100 Subject: [PATCH 30/68] Document explicitly that dotfiles and vcs files are ignored by default This change makes it clear whether or not each of those two options are enabled by default. Without this documentation one has to look into the code. --- src/Symfony/Component/Finder/Finder.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 5784df439b0bf..7b4d71d74eb38 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -402,6 +402,8 @@ public function exclude($dirs) /** * Excludes "hidden" directories and files (starting with a dot). * + * This option is enabled by default. + * * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not * * @return $this @@ -422,6 +424,8 @@ public function ignoreDotFiles($ignoreDotFiles) /** * Forces the finder to ignore version control directories. * + * This option is enabled by default. + * * @param bool $ignoreVCS Whether to exclude VCS files or not * * @return $this From a9568d7c60a5251c651cb0f4d46f8acc8a6a4003 Mon Sep 17 00:00:00 2001 From: Zan Baldwin Date: Thu, 8 Feb 2018 14:20:36 +0000 Subject: [PATCH 31/68] Update Repository Symlink Helper Add workaround for GLOB_BRACE, which is unavailable on certain platforms (such as Alpine). --- link | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/link b/link index a5030d0683379..6a2ec15e22102 100755 --- a/link +++ b/link @@ -37,7 +37,12 @@ if (!is_dir("$argv[1]/vendor/symfony")) { $sfPackages = array('symfony/symfony' => __DIR__); $filesystem = new Filesystem(); -foreach (glob(__DIR__.'/src/Symfony/{Bundle,Bridge,Component,Component/Security}/*', GLOB_BRACE | GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { +$braces = array('Bundle', 'Bridge', 'Component', 'Component/Security'); +$directories = call_user_func_array('array_merge', array_values(array_map(function ($part) { + return glob(__DIR__.'/src/Symfony/'.$part.'/*', GLOB_ONLYDIR | GLOB_NOSORT); +}, $braces))); + +foreach ($directories as $dir) { if ($filesystem->exists($composer = "$dir/composer.json")) { $sfPackages[json_decode(file_get_contents($composer))->name] = $dir; } From 97370a3dd9b34bc6447b8921be611d200cdbac14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Thu, 1 Feb 2018 23:45:44 +0100 Subject: [PATCH 32/68] [Bridge\PhpUnit] Exit as late as possible People might want to register other shutdown functions that should be able to control the exit code themselves, without the deprecation error handler taking over. The php manual says: > If you call exit() within one registered shutdown function, processing > will stop completely and no other registered shutdown functions will be > called. See https://secure.php.net/manual/en/function.register-shutdown-function.php --- .../PhpUnit/DeprecationErrorHandler.php | 53 +++++++---- .../DeprecationErrorHandler/default.phpt | 5 + .../shutdown_deprecations.phpt | 91 +++++++++++++++++++ 3 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index f73690db00553..b0f241c862496 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -127,32 +127,53 @@ public static function register($mode = false) return $b['count'] - $a['count']; }; - foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { - if ($deprecations[$group.'Count']) { - echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; + $displayDeprecations = function ($deprecations) use ($colorize, $cmp) { + foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { + if ($deprecations[$group.'Count']) { + echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; - uasort($deprecations[$group], $cmp); + uasort($deprecations[$group], $cmp); - foreach ($deprecations[$group] as $msg => $notices) { - echo "\n ", $notices['count'], 'x: ', $msg, "\n"; + foreach ($deprecations[$group] as $msg => $notices) { + echo "\n ", $notices['count'], 'x: ', $msg, "\n"; - arsort($notices); + arsort($notices); - foreach ($notices as $method => $count) { - if ('count' !== $method) { - echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; + foreach ($notices as $method => $count) { + if ('count' !== $method) { + echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; + } } } } } - } - if (!empty($notices)) { - echo "\n"; - } + if (!empty($notices)) { + echo "\n"; + } + }; + + $displayDeprecations($deprecations); - if ('weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) { - exit(1); + // store failing status + $isFailing = 'weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other']); + + // reset deprecations array + foreach ($deprecations as $group => $arrayOrInt) { + $deprecations[$group] = is_int($arrayOrInt) ? 0 : array(); } + + register_shutdown_function(function () use (&$deprecations, $isFailing, $displayDeprecations, $mode) { + foreach ($deprecations as $group => $arrayOrInt) { + if (0 < (is_int($arrayOrInt) ? $arrayOrInt : count($arrayOrInt))) { + echo "Shutdown-time deprecations:\n"; + break; + } + } + $displayDeprecations($deprecations); + if ($isFailing || 'weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) { + exit(1); + } + }); }); } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt index 39a3e985865fd..7a0595a7ddebc 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt @@ -59,6 +59,10 @@ $foo = new FooTestCase(); $foo->testLegacyFoo(); $foo->testNonLegacyBar(); +register_shutdown_function(function () { + exit('I get precedence over any exit statements inside the deprecation error handler.'); +}); + ?> --EXPECTF-- Unsilenced deprecation notices (3) @@ -80,3 +84,4 @@ Other deprecation notices (1) 1x: root deprecation +I get precedence over any exit statements inside the deprecation error handler. diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt new file mode 100644 index 0000000000000..fddeed6085dea --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt @@ -0,0 +1,91 @@ +--TEST-- +Test DeprecationErrorHandler in default mode +--FILE-- +testLegacyFoo(); +$foo->testNonLegacyBar(); + +register_shutdown_function(function () { + @trigger_error('root deprecation during shutdown', E_USER_DEPRECATED); +}); + +?> +--EXPECTF-- +Unsilenced deprecation notices (3) + + 2x: unsilenced foo deprecation + 2x in FooTestCase::testLegacyFoo + + 1x: unsilenced bar deprecation + 1x in FooTestCase::testNonLegacyBar + +Remaining deprecation notices (1) + + 1x: silenced bar deprecation + 1x in FooTestCase::testNonLegacyBar + +Legacy deprecation notices (1) + +Other deprecation notices (1) + + 1x: root deprecation + +Shutdown-time deprecations: + +Other deprecation notices (1) + + 1x: root deprecation during shutdown From a0d8b04f7fe93de908869633ebaa5647d051384b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rokas=20Mikalk=C4=97nas?= Date: Mon, 12 Feb 2018 08:50:32 +0200 Subject: [PATCH 33/68] Typo fix in security component lithuanian translation. --- .../Security/Core/Resources/translations/security.lt.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf index da6c332b43829..63e1ed662ee37 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf @@ -8,7 +8,7 @@ Authentication credentials could not be found. - Nepavyko rasti autentifikacijos duomneų. + Nepavyko rasti autentifikacijos duomenų. Authentication request could not be processed due to a system problem. From 2f7f9efbc67c400141242c1a0e12b486ef161af1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 12 Feb 2018 08:05:20 +0100 Subject: [PATCH 34/68] fixed typo --- .../Component/Security/Resources/translations/security.lt.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Resources/translations/security.lt.xlf b/src/Symfony/Component/Security/Resources/translations/security.lt.xlf index da6c332b43829..63e1ed662ee37 100644 --- a/src/Symfony/Component/Security/Resources/translations/security.lt.xlf +++ b/src/Symfony/Component/Security/Resources/translations/security.lt.xlf @@ -8,7 +8,7 @@ Authentication credentials could not be found. - Nepavyko rasti autentifikacijos duomneų. + Nepavyko rasti autentifikacijos duomenų. Authentication request could not be processed due to a system problem. From 60abecafb91dce9d4cccc7fb7abcff3ea3ccc762 Mon Sep 17 00:00:00 2001 From: ergiegonzaga <36328355+ergiegonzaga@users.noreply.github.com> Date: Sat, 10 Feb 2018 18:44:21 +0800 Subject: [PATCH 35/68] [Security][Validator] Add translations for Tagalog --- .../Resources/translations/security.tl.xlf | 71 ++++ .../Resources/translations/validators.tl.xlf | 319 ++++++++++++++++++ 2 files changed, 390 insertions(+) create mode 100644 src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf create mode 100644 src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf new file mode 100644 index 0000000000000..c74b10aea83ab --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf @@ -0,0 +1,71 @@ + + + + + + An authentication exception occurred. + Isang pambihirang pagpaptunay ang nangyari. + + + Authentication credentials could not be found. + Hindi mahanap ang mga kinakailangan na dokumento para sa pagpapatunay. + + + Authentication request could not be processed due to a system problem. + Hindi maproseso ang iyong hiling dahil may problema sa sistema. + + + Invalid credentials. + Hindi balidong mga dokumento. + + + Cookie has already been used by someone else. + Ang Cookie ay ginamit na ng ibang tao. + + + Not privileged to request the resource. + Walang pribilehiyo upang humingi ng mga bagong mapagkukunan. + + + Invalid CSRF token. + Hindi balidong mga token ng CSRF. + + + Digest nonce has expired. + Na-expire na ang Digest nonce. + + + No authentication provider found to support the authentication token. + Walang nakitang nagbibibagay ng suporta sa token ng pagpapatunay. + + + No session available, it either timed out or cookies are not enabled. + Walang sesyon ng magagamit, ito ay nawalan ng oras o hindi pinagana. + + + No token could be found. + Walang token na nahanap. + + + Username could not be found. + Walang username na makita. + + + Account has expired. + Ang akawnt ay nag-expire na. + + + Credentials have expired. + .ng mga kinakailangang dokumento ay nag expire na. + + + Account is disabled. + Ang akawnt ay hindi pinagana. + + + Account is locked. + ng akawnt ay nakasara. + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf new file mode 100644 index 0000000000000..75dc329589730 --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf @@ -0,0 +1,319 @@ + + + + + + This value should be false. + Ang halaga nito ay dapat na huwad. + + + This value should be true. + Ang halaga nito ay dapat totoo. + + + This value should be of type {{ type }}. + Ang halaga nito ay dapat sa uri {{ type }}. + + + This value should be blank. + Ang halaga nito ay dapat walang laman. + + + The value you selected is not a valid choice. + Ang halaga ng iyong pinili ay hindi balidong pagpili. + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + Kailangan mong pumili ng pinakamababang {{ limit }} ng pagpilian.|Kailangan mong pumili ng pinakamababang {{ limit }} ng mga pagpipilian. + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + Kailangan mong pumili ng pinakamataas {{ limit }} ng pagpipilian.|Kailangan mong pumili ng pinakamataas {{ limit }} ng mga pagpipilian. + + + One or more of the given values is invalid. + Isa o higit pang mga halaga na binigay ay hindi balido. + + + This field was not expected. + Ang larangang ito ay hindi inaasahan. + + + This field is missing. + Ang patlang na ito ay nawawala. + + + This value is not a valid date. + Ang halagang ito ay hindi balidong petsa. + + + This value is not a valid datetime. + Ang halagang ito ay hindi wastong petsa/oras. + + + This value is not a valid email address. + Ang halagang ito ay hindi balidong address ng email. + + + The file could not be found. + Ang file na ito ay hindi makita. + + + The file is not readable. + Ang file na ito ay hindi mabasa. + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + Ang file na ito ay masyadong malaki ({{ size }} {{ suffix }}). Ang pinakamalaking sukat {{ limit }} {{ suffix }}. + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + Ang uri ng file ng mime ay hindi balido ({{ type }}).Ang mga pinapayagang uri ng mime ay ang {{ types }}. + + + This value should be {{ limit }} or less. + Ang halaga nito ay dapat na {{ limit }} or maliit pa. + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + Ang halaga nito ay masyadong mahaba.Ito ay dapat na {{ limit }} karakter o maliit pa.|Ang halaga nito ay masyadong mahaba. Ito ay dapat na {{ limit }} mga karakter o maliit pa. + + + This value should be {{ limit }} or more. + Ang halaga nito ay dapat na {{ limit }} o mas marami pa. + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + Ang halaga nito ay masyadong maliit. Ito ay dapat na {{ limit }} karakter o marami pa.|Ang halaga nito ay masyadong maliit. Ito ay dapat na {{ limit }} mga karakter o marami pa. + + + This value should not be blank. + Ang halaga na ito ay dapat na may laman. + + + This value should not be null. + Meron dapt itong halaga. + + + This value should be null. + Wala dapat itong halaga. + + + This value is not valid. + Hindi balido ang halagang ito. + + + This value is not a valid time. + Ang halagang ito ay hindi wastong oras. + + + This value is not a valid URL. + Hindi ito isang balidong URL. + + + The two values should be equal. + Ang dalwang halaga ay dapat magkapareha. + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + Ang file ay masyadong malaki. Ang pinapayagan halaga lamang ay {{ limit}} {{ suffix }}. + + + The file is too large. + Ang file na ito ay masyadong malaki. + + + The file could not be uploaded. + Ang file na ito ay hindi ma-upload. + + + This value should be a valid number. + Ang halaga nito ay dapat na wastong numero. + + + This file is not a valid image. + Ang file na ito ay hindi wastong imahe. + + + This is not a valid IP address. + Ito ay hindi wastong IP address. + + + This value is not a valid language. + Ang halaga na ito ay hindi balidong wika. + + + This value is not a valid locale. + Ito ay isang hindi wastong locale na halaga. + + + This value is not a valid country. + ng halaga na ito ay hindi wastong bansa. + + + This value is already used. + Ang halaga na ito ay ginamit na. + + + The size of the image could not be detected. + Ang sukat ng imahe ay hindi madetect. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Ang lapad ng imahe ay masyadong malaki ({{ width }}px). Ang pinapayagang lapay ay {{ max_width }}px. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Ang lapad ng imahe ay masyadong maliit ({{ width }}px). Ang pinakamaliit na pinapayagang lapad ay {{ min_width }}px. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Ang haba ng imahe ay masyadong mataas ({{ height }}px). Ang pinakmataas na haba ay {{ max_height }}px. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Ang haba ng imahe ay masyadong maliit ({{ height }}px). Ang inaasahang haba ay {{ min_height }}px. + + + This value should be the user's current password. + Ang halagang ito ay dapat na password ng kasalukuyang gumagamit. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Ang halagang ito ay dapat na eksakto sa {{ limit}} karakter.|Ang halagang ito ay dapat na eksakto sa {{ limit }} mga karakter. + + + The file was only partially uploaded. + Ang file na ito ay kahalating na upload lamang. + + + No file was uploaded. + Walang na upload na file. + + + No temporary folder was configured in php.ini. + Walang temporaryong folder ang naayos sa php.ini. + + + Cannot write temporary file to disk. + Temporaryong hindi makasulat ng file sa disk. + + + A PHP extension caused the upload to fail. + Ang dahilan ng pagkabigo ng pagupload ng files ay isang extension ng PHP. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} elemento o marami pa.|Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} mga elemento o marami pa. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} elemento o maliit pa.|Ang koleksyon na ito ay dapat magkaroon ng {{ limit }} mga elemento o maliit pa. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Ang koleksyong ito ay magkaroon ng eksaktong {{ limit }} elemento.|Ang koleksyong ito ay magkaroon ng eksaktong {{ limit }} mga elemento. + + + Invalid card number. + Hindi wastong numero ng kard. + + + Unsupported card type or invalid card number. + Hindi supportadong uri ng kard o hindi wastong numero ng kard. + + + This is not a valid International Bank Account Number (IBAN). + Ito ay hindi isang balidong International Bank Account Number (IBAN). + + + This value is not a valid ISBN-10. + Ang halagang ito ay hindi balidong SBN-10. + + + This value is not a valid ISBN-13. + Ang halagang ito ay hindi balidong ISBN-13. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Ang halagang ito ay pwdeng isang balidong ISBN-10 o isang balidong ISBN-13. + + + This value is not a valid ISSN. + Ang halangang ito ay hindi isang balidong ISSN. + + + This value is not a valid currency. + Ang halagang ito ay hindi balidong pera. + + + This value should be equal to {{ compared_value }}. + Ito ay hindi dapat magkapareho sa {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Ang halagang ito ay dapat tataas sa {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Ang halagang ito ay dapat mas mataas o magkapareha sa {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Ang halagang ito ay dapat kapareha ng {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Ang halagang ito ay dapat mas maliit sa {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Ang halagang ito ay dapat mas mmaliit o magkapareha sa {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Ang halagang ito ay hindi dapat magkapareha sa {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Ang halagang ito ay hindi dapat magkapareha sa {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Ang ratio ng imahe ay masyadong malaki ({{ ratio }}). Ang pinakamalaking ratio ay {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + ng ratio ng imahe ay masyadong maliit ({{ ratio }}). Ang pinamaliit na ratio ay {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Ang imahe ay kwadrado ({{ width }}x{{ height }}px). Ang mga kwadradong imahe ay hindi pwede. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Ang orientasyon ng imahe ay nakalandscape ({{ width }}x{{ height }}px). Ang mga imaheng nakalandscape ang orientasyon ay hindi pwede. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Ang orientasyon ng imahe ay nakaportrait ({{ width }}x{{ height }}px). PAng mga imaheng nakaportrait ang orientasyon ay hindi pwede. + + + An empty file is not allowed. + Ang file na walang laman ay hindi pwede. + + + The host could not be resolved. + Hindi maresolba ang host. + + + This value does not match the expected {{ charset }} charset. + Ang halaga ay hindi kapareha sa inaasahang {{ charset }} set ng karater. + + + This is not a valid Business Identifier Code (BIC). + Ito ay hindi isang balidong Business Identifier Code (BIC). + + + + From 45d288a4ae365c10035775cacee7262df1b92c7f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Feb 2018 15:12:46 +0100 Subject: [PATCH 36/68] Add security.tl.xlf to legacy directory --- .../Resources/translations/security.tl.xlf | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/Symfony/Component/Security/Resources/translations/security.tl.xlf diff --git a/src/Symfony/Component/Security/Resources/translations/security.tl.xlf b/src/Symfony/Component/Security/Resources/translations/security.tl.xlf new file mode 100644 index 0000000000000..c74b10aea83ab --- /dev/null +++ b/src/Symfony/Component/Security/Resources/translations/security.tl.xlf @@ -0,0 +1,71 @@ + + + + + + An authentication exception occurred. + Isang pambihirang pagpaptunay ang nangyari. + + + Authentication credentials could not be found. + Hindi mahanap ang mga kinakailangan na dokumento para sa pagpapatunay. + + + Authentication request could not be processed due to a system problem. + Hindi maproseso ang iyong hiling dahil may problema sa sistema. + + + Invalid credentials. + Hindi balidong mga dokumento. + + + Cookie has already been used by someone else. + Ang Cookie ay ginamit na ng ibang tao. + + + Not privileged to request the resource. + Walang pribilehiyo upang humingi ng mga bagong mapagkukunan. + + + Invalid CSRF token. + Hindi balidong mga token ng CSRF. + + + Digest nonce has expired. + Na-expire na ang Digest nonce. + + + No authentication provider found to support the authentication token. + Walang nakitang nagbibibagay ng suporta sa token ng pagpapatunay. + + + No session available, it either timed out or cookies are not enabled. + Walang sesyon ng magagamit, ito ay nawalan ng oras o hindi pinagana. + + + No token could be found. + Walang token na nahanap. + + + Username could not be found. + Walang username na makita. + + + Account has expired. + Ang akawnt ay nag-expire na. + + + Credentials have expired. + .ng mga kinakailangang dokumento ay nag expire na. + + + Account is disabled. + Ang akawnt ay hindi pinagana. + + + Account is locked. + ng akawnt ay nakasara. + + + + From d317496b6b7f783c4a76871c169eb05cda3c714c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Feb 2018 15:17:16 +0100 Subject: [PATCH 37/68] [Process] fix test case --- src/Symfony/Component/Process/PhpExecutableFinder.php | 2 +- src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index 25415eda793bd..4bc27fe4d4574 100644 --- a/src/Symfony/Component/Process/PhpExecutableFinder.php +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -62,7 +62,7 @@ public function find($includeArgs = true) } } - if (is_executable($php = PHP_BINDIR.'/php'.('\\' === DIRECTORY_SEPARATOR ? '.exe' : ''))) { + if (is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { return $php; } diff --git a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php index 23465e9e808d1..250534d675a90 100644 --- a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php +++ b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php @@ -94,7 +94,7 @@ public function testFindWithSuffix() //TODO maybe php executable is custom or even Windows if ('\\' === DIRECTORY_SEPARATOR) { $this->assertTrue(is_executable($current)); - $this->assertTrue((bool) preg_match('/'.addslashes(DIRECTORY_SEPARATOR).'php\.(exe|bat|cmd|com)$/i', $current), '::find() returns the executable PHP with suffixes'); + $this->assertRegExp('/\\\\php\.(exe|bat|cmd|com)$/i', $current, '::find() returns the executable PHP with suffixes'); } } } From 92842814f6693ee3c4e24cca5d061eb4de50eb5d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Feb 2018 21:27:30 +0100 Subject: [PATCH 38/68] [Routing] Throw 405 instead of 404 when redirect is not possible --- .../Matcher/Dumper/PhpMatcherDumper.php | 55 +++++++++++-------- .../Tests/Fixtures/dumper/url_matcher2.php | 15 +++++ .../DumpedRedirectableUrlMatcherTest.php | 8 +++ 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 28ab3679f9fa8..ac48ca978fd3f 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -217,7 +217,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $methods[] = 'HEAD'; } - $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); + $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('GET', $methods)); if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) { @@ -258,34 +258,13 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren EOF; $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); - if ($methods) { - if (1 === count($methods)) { - $code .= <<context->getMethod() != '$methods[0]') { - \$allow[] = '$methods[0]'; - goto $gotoname; - } - - -EOF; - } else { - $methods = implode("', '", $methods); - $code .= <<context->getMethod(), array('$methods'))) { - \$allow = array_merge(\$allow, array('$methods')); - goto $gotoname; - } - - -EOF; - } - } if ($hasTrailingSlash) { $code .= <<context->getMethod(), array('HEAD', 'GET'))) { + \$allow[] = 'GET'; goto $gotoname; } else { return \$this->redirect(\$rawPathinfo.'/', '$name'); @@ -303,6 +282,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $code .= <<context->getScheme()])) { + if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) { + \$allow[] = 'GET'; + goto $gotoname; + } + return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)); } @@ -310,6 +294,29 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren EOF; } + if ($methods) { + if (1 === count($methods)) { + $code .= <<context->getMethod() != '$methods[0]') { + \$allow[] = '$methods[0]'; + goto $gotoname; + } + + +EOF; + } else { + $methods = implode("', '", $methods); + $code .= <<context->getMethod(), array('$methods'))) { + \$allow = array_merge(\$allow, array('$methods')); + goto $gotoname; + } + + +EOF; + } + } + // optimize parameters array if ($matches || $hostMatches) { $vars = array(); @@ -333,7 +340,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } $code .= " }\n"; - if ($methods || $hasTrailingSlash) { + if ($hasTrailingSlash || $schemes || $methods) { $code .= " $gotoname:\n"; } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index a7e7ce75be537..467d53b3ed2df 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -69,6 +69,7 @@ public function match($rawPathinfo) if ('/' === substr($pathinfo, -1)) { // no-op } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + $allow[] = 'GET'; goto not_baz3; } else { return $this->redirect($rawPathinfo.'/', 'baz3'); @@ -85,6 +86,7 @@ public function match($rawPathinfo) if ('/' === substr($pathinfo, -1)) { // no-op } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + $allow[] = 'GET'; goto not_baz4; } else { return $this->redirect($rawPathinfo.'/', 'baz4'); @@ -183,6 +185,7 @@ public function match($rawPathinfo) if ('/' === substr($pathinfo, -1)) { // no-op } elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + $allow[] = 'GET'; goto not_hey; } else { return $this->redirect($rawPathinfo.'/', 'hey'); @@ -333,21 +336,33 @@ public function match($rawPathinfo) if ('/secure' === $pathinfo) { $requiredSchemes = array ( 'https' => 0,); if (!isset($requiredSchemes[$this->context->getScheme()])) { + if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + $allow[] = 'GET'; + goto not_secure; + } + return $this->redirect($rawPathinfo, 'secure', key($requiredSchemes)); } return array('_route' => 'secure'); } + not_secure: // nonsecure if ('/nonsecure' === $pathinfo) { $requiredSchemes = array ( 'http' => 0,); if (!isset($requiredSchemes[$this->context->getScheme()])) { + if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + $allow[] = 'GET'; + goto not_nonsecure; + } + return $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes)); } return array('_route' => 'nonsecure'); } + not_nonsecure: throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php index 28f65aeeb5aa7..7ea8aa2834167 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php @@ -19,6 +19,14 @@ class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest { + /** + * @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException + */ + public function testRedirectWhenNoSlashForNonSafeMethod() + { + parent::testRedirectWhenNoSlashForNonSafeMethod(); + } + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) { static $i = 0; From 6d4e5e0d0ae329b43cd3966d4afb0583be6233fa Mon Sep 17 00:00:00 2001 From: Ergie Gonzaga <36328355+ergiegonzaga@users.noreply.github.com> Date: Tue, 13 Feb 2018 11:42:56 +0800 Subject: [PATCH 39/68] [Form] Add translations for Tagalog --- .../Resources/translations/validators.tl.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/Symfony/Component/Form/Resources/translations/validators.tl.xlf diff --git a/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf new file mode 100644 index 0000000000000..02def0bf31f6f --- /dev/null +++ b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + Ang pormang itong ay hindi dapat magkarron ng dagdag na mga patlang. + + + The uploaded file was too large. Please try to upload a smaller file. + Ang ini-upload na file ay masyadong malaki. Pakiulit muling mag-upload ng mas maliit na file. + + + The CSRF token is invalid. Please try to resubmit the form. + Hindi balido ang CSRF token. Maagpasa muli ng isang pang porma. + + + + From 1fc5df683b99374c7210d677f002f1dc9373c106 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 14 Feb 2018 10:05:17 +0100 Subject: [PATCH 40/68] fix accessing request values --- .../Http/Firewall/SimpleFormAuthenticationListener.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php index 1ec87da4cb1a3..9d87c59c888eb 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php @@ -119,9 +119,13 @@ protected function attemptAuthentication(Request $request) } } - $requestBag = $this->options['post_only'] ? $request->request : $request; - $username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']); - $password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']); + if ($this->options['post_only']) { + $username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']); + $password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']); + } else { + $username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']); + $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); + } if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) { throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username))); From 8ee83879ebec38c8a2eb19f9948c2cb89518c11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 11 Feb 2018 19:19:04 +0100 Subject: [PATCH 41/68] [Serializer] optims and cleanup --- .../Serializer/Annotation/Groups.php | 10 +++---- .../Serializer/Encoder/JsonEncoder.php | 2 +- .../Serializer/Encoder/XmlEncoder.php | 28 +++++++++---------- .../Serializer/Mapping/AttributeMetadata.php | 2 +- .../Mapping/Factory/ClassMetadataFactory.php | 6 ++-- .../Serializer/Mapping/Loader/LoaderChain.php | 2 +- .../Mapping/Loader/YamlFileLoader.php | 10 +++---- .../CamelCaseToSnakeCaseNameConverter.php | 6 ++-- .../Normalizer/AbstractNormalizer.php | 20 ++++++------- .../Normalizer/GetSetMethodNormalizer.php | 16 +++++------ .../Normalizer/ObjectNormalizer.php | 10 +++---- .../Normalizer/PropertyNormalizer.php | 12 ++++---- .../Component/Serializer/Serializer.php | 6 ++-- 13 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/Symfony/Component/Serializer/Annotation/Groups.php b/src/Symfony/Component/Serializer/Annotation/Groups.php index d0339552a74f4..be29135ae8d97 100644 --- a/src/Symfony/Component/Serializer/Annotation/Groups.php +++ b/src/Symfony/Component/Serializer/Annotation/Groups.php @@ -34,16 +34,16 @@ class Groups public function __construct(array $data) { if (!isset($data['value']) || !$data['value']) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" cannot be empty.', get_class($this))); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" cannot be empty.', \get_class($this))); } - if (!is_array($data['value'])) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be an array of strings.', get_class($this))); + if (!\is_array($data['value'])) { + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be an array of strings.', \get_class($this))); } foreach ($data['value'] as $group) { - if (!is_string($group)) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be an array of strings.', get_class($this))); + if (!\is_string($group)) { + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be an array of strings.', \get_class($this))); } } diff --git a/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php b/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php index 66d94f85af858..2a084f1426a35 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonEncoder.php @@ -96,7 +96,7 @@ public function supportsDecoding($format) */ public static function getLastErrorMessage() { - if (function_exists('json_last_error_msg')) { + if (\function_exists('json_last_error_msg')) { return json_last_error_msg(); } diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index 005b565d12113..5ce58fb07bd9a 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -179,7 +179,7 @@ public function getRootNodeName() */ final protected function appendXMLString(\DOMNode $node, $val) { - if (strlen($val) > 0) { + if (\strlen($val) > 0) { $frag = $this->dom->createDocumentFragment(); $frag->appendXML($val); $node->appendChild($frag); @@ -260,17 +260,17 @@ private function parseXml(\DOMNode $node) $value = $this->parseXmlValue($node); - if (!count($data)) { + if (!\count($data)) { return $value; } - if (!is_array($value)) { + if (!\is_array($value)) { $data['#'] = $value; return $data; } - if (1 === count($value) && key($value)) { + if (1 === \count($value) && key($value)) { $data[key($value)] = current($value); return $data; @@ -326,7 +326,7 @@ private function parseXmlValue(\DOMNode $node) return $node->nodeValue; } - if (1 === $node->childNodes->length && in_array($node->firstChild->nodeType, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE))) { + if (1 === $node->childNodes->length && \in_array($node->firstChild->nodeType, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE))) { return $node->firstChild->nodeValue; } @@ -351,7 +351,7 @@ private function parseXmlValue(\DOMNode $node) } foreach ($value as $key => $val) { - if (is_array($val) && 1 === count($val)) { + if (\is_array($val) && 1 === \count($val)) { $value[$key] = current($val); } } @@ -374,7 +374,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) { $append = true; - if (is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) { + if (\is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) { foreach ($data as $key => $data) { //Ah this is the magic @ attribute types. if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) { @@ -384,7 +384,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) $parentNode->setAttribute($attributeName, $data); } elseif ('#' === $key) { $append = $this->selectNodeType($parentNode, $data); - } elseif (is_array($data) && false === is_numeric($key)) { + } elseif (\is_array($data) && false === is_numeric($key)) { // Is this array fully numeric keys? if (ctype_digit(implode('', array_keys($data)))) { /* @@ -408,7 +408,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) return $append; } - if (is_object($data)) { + if (\is_object($data)) { $data = $this->serializer->normalize($data, $this->format, $this->context); if (null !== $data && !is_scalar($data)) { return $this->buildXml($parentNode, $data, $xmlRootNodeName); @@ -477,22 +477,22 @@ private function needsCdataWrapping($val) */ private function selectNodeType(\DOMNode $node, $val) { - if (is_array($val)) { + if (\is_array($val)) { return $this->buildXml($node, $val); } elseif ($val instanceof \SimpleXMLElement) { $child = $this->dom->importNode(dom_import_simplexml($val), true); $node->appendChild($child); } elseif ($val instanceof \Traversable) { $this->buildXml($node, $val); - } elseif (is_object($val)) { + } elseif (\is_object($val)) { return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context)); } elseif (is_numeric($val)) { return $this->appendText($node, (string) $val); - } elseif (is_string($val) && $this->needsCdataWrapping($val)) { + } elseif (\is_string($val) && $this->needsCdataWrapping($val)) { return $this->appendCData($node, $val); - } elseif (is_string($val)) { + } elseif (\is_string($val)) { return $this->appendText($node, $val); - } elseif (is_bool($val)) { + } elseif (\is_bool($val)) { return $this->appendText($node, (int) $val); } elseif ($val instanceof \DOMNode) { $child = $this->dom->importNode($val, true); diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php index 600e17be4f976..1d8496179a1f5 100644 --- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php +++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php @@ -55,7 +55,7 @@ public function getName() */ public function addGroup($group) { - if (!in_array($group, $this->groups)) { + if (!\in_array($group, $this->groups)) { $this->groups[] = $group; } } diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php index 2babf7e27d442..c058e021df42c 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -40,7 +40,7 @@ public function getMetadataFor($value) { $class = $this->getClass($value); if (!$class) { - throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value))); + throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', \gettype($value))); } if (isset($this->loadedClasses[$class])) { @@ -96,10 +96,10 @@ public function hasMetadataFor($value) */ private function getClass($value) { - if (!is_object($value) && !is_string($value)) { + if (!\is_object($value) && !\is_string($value)) { return false; } - return ltrim(is_object($value) ? get_class($value) : $value, '\\'); + return ltrim(\is_object($value) ? \get_class($value) : $value, '\\'); } } diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/LoaderChain.php b/src/Symfony/Component/Serializer/Mapping/Loader/LoaderChain.php index 3b0192b7e458c..461001fe57543 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/LoaderChain.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/LoaderChain.php @@ -40,7 +40,7 @@ public function __construct(array $loaders) { foreach ($loaders as $loader) { if (!$loader instanceof LoaderInterface) { - throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader))); + throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', \get_class($loader))); } } diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php index be2de7b6f1aff..ac48d8161439d 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php @@ -30,7 +30,7 @@ class YamlFileLoader extends FileLoader * * @var array */ - private $classes = null; + private $classes; /** * {@inheritdoc} @@ -53,7 +53,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata) } // not an array - if (!is_array($classes)) { + if (!\is_array($classes)) { throw new MappingException(sprintf('The file "%s" must contain a YAML array.', $this->file)); } @@ -66,7 +66,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata) $yaml = $this->classes[$classMetadata->getName()]; - if (isset($yaml['attributes']) && is_array($yaml['attributes'])) { + if (isset($yaml['attributes']) && \is_array($yaml['attributes'])) { $attributesMetadata = $classMetadata->getAttributesMetadata(); foreach ($yaml['attributes'] as $attribute => $data) { @@ -78,12 +78,12 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata) } if (isset($data['groups'])) { - if (!is_array($data['groups'])) { + if (!\is_array($data['groups'])) { throw new MappingException(sprintf('The "groups" key must be an array of strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); } foreach ($data['groups'] as $group) { - if (!is_string($group)) { + if (!\is_string($group)) { throw new MappingException(sprintf('Group names must be strings in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); } diff --git a/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php b/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php index ca2705cf2ac6c..9241d40357268 100644 --- a/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php +++ b/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php @@ -36,11 +36,11 @@ public function __construct(array $attributes = null, $lowerCamelCase = true) */ public function normalize($propertyName) { - if (null === $this->attributes || in_array($propertyName, $this->attributes)) { + if (null === $this->attributes || \in_array($propertyName, $this->attributes)) { $lcPropertyName = lcfirst($propertyName); $snakeCasedName = ''; - $len = strlen($lcPropertyName); + $len = \strlen($lcPropertyName); for ($i = 0; $i < $len; ++$i) { if (ctype_upper($lcPropertyName[$i])) { $snakeCasedName .= '_'.strtolower($lcPropertyName[$i]); @@ -68,7 +68,7 @@ public function denormalize($propertyName) $camelCasedName = lcfirst($camelCasedName); } - if (null === $this->attributes || in_array($camelCasedName, $this->attributes)) { + if (null === $this->attributes || \in_array($camelCasedName, $this->attributes)) { return $camelCasedName; } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 031bcf7d08c5c..88f5f9273dae4 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -100,7 +100,7 @@ public function setCircularReferenceLimit($circularReferenceLimit) */ public function setCircularReferenceHandler($circularReferenceHandler) { - if (!is_callable($circularReferenceHandler)) { + if (!\is_callable($circularReferenceHandler)) { throw new InvalidArgumentException('The given circular reference handler is not callable.'); } @@ -121,7 +121,7 @@ public function setCircularReferenceHandler($circularReferenceHandler) public function setCallbacks(array $callbacks) { foreach ($callbacks as $attribute => $callback) { - if (!is_callable($callback)) { + if (!\is_callable($callback)) { throw new InvalidArgumentException(sprintf( 'The given callback for attribute "%s" is not callable.', $attribute @@ -220,10 +220,10 @@ protected function isCircularReference($object, &$context) protected function handleCircularReference($object) { if ($this->circularReferenceHandler) { - return call_user_func($this->circularReferenceHandler, $object); + return \call_user_func($this->circularReferenceHandler, $object); } - throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', get_class($object), $this->circularReferenceLimit)); + throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', \get_class($object), $this->circularReferenceLimit)); } /** @@ -253,13 +253,13 @@ protected function formatAttribute($attributeName) */ protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) { - if (!$this->classMetadataFactory || !isset($context[static::GROUPS]) || !is_array($context[static::GROUPS])) { + if (!$this->classMetadataFactory || !isset($context[static::GROUPS]) || !\is_array($context[static::GROUPS])) { return false; } $allowedAttributes = array(); foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesMetadata() as $attributeMetadata) { - if (count(array_intersect($attributeMetadata->getGroups(), $context[static::GROUPS]))) { + if (array_intersect($attributeMetadata->getGroups(), $context[static::GROUPS])) { $allowedAttributes[] = $attributesAsString ? $attributeMetadata->getName() : $attributeMetadata; } } @@ -302,7 +302,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref { if ( isset($context[static::OBJECT_TO_POPULATE]) && - is_object($context[static::OBJECT_TO_POPULATE]) && + \is_object($context[static::OBJECT_TO_POPULATE]) && $context[static::OBJECT_TO_POPULATE] instanceof $class ) { $object = $context[static::OBJECT_TO_POPULATE]; @@ -320,11 +320,11 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref $paramName = $constructorParameter->name; $key = $this->nameConverter ? $this->nameConverter->normalize($paramName) : $paramName; - $allowed = false === $allowedAttributes || in_array($paramName, $allowedAttributes); - $ignored = in_array($paramName, $this->ignoredAttributes); + $allowed = false === $allowedAttributes || \in_array($paramName, $allowedAttributes); + $ignored = \in_array($paramName, $this->ignoredAttributes); if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) { if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { - if (!is_array($data[$paramName])) { + if (!\is_array($data[$paramName])) { throw new RuntimeException(sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name)); } diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 6eec32160d02e..d8cfc1d201d45 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -58,17 +58,17 @@ public function normalize($object, $format = null, array $context = array()) foreach ($reflectionMethods as $method) { if ($this->isGetMethod($method)) { $attributeName = lcfirst(substr($method->name, 0 === strpos($method->name, 'is') ? 2 : 3)); - if (in_array($attributeName, $this->ignoredAttributes)) { + if (\in_array($attributeName, $this->ignoredAttributes)) { continue; } - if (false !== $allowedAttributes && !in_array($attributeName, $allowedAttributes)) { + if (false !== $allowedAttributes && !\in_array($attributeName, $allowedAttributes)) { continue; } $attributeValue = $method->invoke($object); if (isset($this->callbacks[$attributeName])) { - $attributeValue = call_user_func($this->callbacks[$attributeName], $attributeValue); + $attributeValue = \call_user_func($this->callbacks[$attributeName], $attributeValue); } if (null !== $attributeValue && !is_scalar($attributeValue)) { if (!$this->serializer instanceof NormalizerInterface) { @@ -108,13 +108,13 @@ public function denormalize($data, $class, $format = null, array $context = arra $attribute = $this->nameConverter->denormalize($attribute); } - $allowed = false === $allowedAttributes || in_array($attribute, $allowedAttributes); - $ignored = in_array($attribute, $this->ignoredAttributes); + $allowed = false === $allowedAttributes || \in_array($attribute, $allowedAttributes); + $ignored = \in_array($attribute, $this->ignoredAttributes); if ($allowed && !$ignored) { $setter = 'set'.ucfirst($attribute); - if (in_array($setter, $classMethods) && !$reflectionClass->getMethod($setter)->isStatic()) { + if (\in_array($setter, $classMethods) && !$reflectionClass->getMethod($setter)->isStatic()) { $object->$setter($value); } } @@ -128,7 +128,7 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsNormalization($data, $format = null) { - return is_object($data) && !$data instanceof \Traversable && $this->supports(get_class($data)); + return \is_object($data) && !$data instanceof \Traversable && $this->supports(\get_class($data)); } /** @@ -166,7 +166,7 @@ private function supports($class) */ private function isGetMethod(\ReflectionMethod $method) { - $methodLength = strlen($method->name); + $methodLength = \strlen($method->name); return !$method->isStatic() && diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index 5c64e156c34e6..dc3a49ff7e115 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -45,7 +45,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory */ public function supportsNormalization($data, $format = null) { - return is_object($data) && !$data instanceof \Traversable; + return \is_object($data) && !$data instanceof \Traversable; } /** @@ -98,14 +98,14 @@ public function normalize($object, $format = null, array $context = array()) } foreach ($attributes as $attribute) { - if (in_array($attribute, $this->ignoredAttributes)) { + if (\in_array($attribute, $this->ignoredAttributes)) { continue; } $attributeValue = $this->propertyAccessor->getValue($object, $attribute); if (isset($this->callbacks[$attribute])) { - $attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue); + $attributeValue = \call_user_func($this->callbacks[$attribute], $attributeValue); } if (null !== $attributeValue && !is_scalar($attributeValue)) { @@ -150,8 +150,8 @@ public function denormalize($data, $class, $format = null, array $context = arra $attribute = $this->nameConverter->denormalize($attribute); } - $allowed = false === $allowedAttributes || in_array($attribute, $allowedAttributes); - $ignored = in_array($attribute, $this->ignoredAttributes); + $allowed = false === $allowedAttributes || \in_array($attribute, $allowedAttributes); + $ignored = \in_array($attribute, $this->ignoredAttributes); if ($allowed && !$ignored) { try { diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index a5764244fe4cc..89e1057277211 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -50,11 +50,11 @@ public function normalize($object, $format = null, array $context = array()) $allowedAttributes = $this->getAllowedAttributes($object, $context, true); foreach ($reflectionObject->getProperties() as $property) { - if (in_array($property->name, $this->ignoredAttributes) || $property->isStatic()) { + if (\in_array($property->name, $this->ignoredAttributes) || $property->isStatic()) { continue; } - if (false !== $allowedAttributes && !in_array($property->name, $allowedAttributes)) { + if (false !== $allowedAttributes && !\in_array($property->name, $allowedAttributes)) { continue; } @@ -66,7 +66,7 @@ public function normalize($object, $format = null, array $context = array()) $attributeValue = $property->getValue($object); if (isset($this->callbacks[$property->name])) { - $attributeValue = call_user_func($this->callbacks[$property->name], $attributeValue); + $attributeValue = \call_user_func($this->callbacks[$property->name], $attributeValue); } if (null !== $attributeValue && !is_scalar($attributeValue)) { if (!$this->serializer instanceof NormalizerInterface) { @@ -105,8 +105,8 @@ public function denormalize($data, $class, $format = null, array $context = arra $propertyName = $this->nameConverter->denormalize($propertyName); } - $allowed = false === $allowedAttributes || in_array($propertyName, $allowedAttributes); - $ignored = in_array($propertyName, $this->ignoredAttributes); + $allowed = false === $allowedAttributes || \in_array($propertyName, $allowedAttributes); + $ignored = \in_array($propertyName, $this->ignoredAttributes); if ($allowed && !$ignored && $reflectionClass->hasProperty($propertyName)) { $property = $reflectionClass->getProperty($propertyName); @@ -131,7 +131,7 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsNormalization($data, $format = null) { - return is_object($data) && !$data instanceof \Traversable && $this->supports(get_class($data)); + return \is_object($data) && !$data instanceof \Traversable && $this->supports(\get_class($data)); } /** diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 37b49f3493b8b..34e4193c6aa45 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -132,7 +132,7 @@ public function normalize($data, $format = null, array $context = array()) return $data; } - if (is_array($data) || $data instanceof \Traversable) { + if (\is_array($data) || $data instanceof \Traversable) { $normalized = array(); foreach ($data as $key => $val) { $normalized[$key] = $this->normalize($val, $format, $context); @@ -141,12 +141,12 @@ public function normalize($data, $format = null, array $context = array()) return $normalized; } - if (is_object($data)) { + if (\is_object($data)) { if (!$this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); } - throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', get_class($data))); + throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', \get_class($data))); } throw new UnexpectedValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true))); From a5f05a04864f67f6738ef83d734039a7b85cc5ac Mon Sep 17 00:00:00 2001 From: "changmin.keum" Date: Thu, 15 Feb 2018 14:08:21 +0900 Subject: [PATCH 42/68] [DI] Add null check for removeChild --- .../Component/DependencyInjection/Loader/XmlFileLoader.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 93ca3c669b7d3..abf91b181ca3e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -324,7 +324,9 @@ private function processAnonymousServices(\DOMDocument $xml, $file) $domElement->parentNode->replaceChild($tmpDomElement, $domElement); $tmpDomElement->setAttribute('id', $id); } else { - $domElement->parentNode->removeChild($domElement); + if (null !== $domElement->parentNode) { + $domElement->parentNode->removeChild($domElement); + } } } } From ba3e19ae21ce4c0cd93b402d262c2a749ecd00a6 Mon Sep 17 00:00:00 2001 From: Ian Jenkins Date: Thu, 15 Feb 2018 15:19:03 +0000 Subject: [PATCH 43/68] [HttpFoundation] Add x-zip-compressed to MimeTypeExtensionGuesser. Zip files uploaded on Windows often have a mime type of `x-zip-compressed`. This patch adds support for this mime type to `MimeTypeExtensionGuesser`. The mime type seems to be a valid mime type for zip files according to http://filext.com/file-extension/ZIP --- .../HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php index 49c323c1f55e8..36271afe4a906 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php @@ -599,6 +599,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'application/x-xliff+xml' => 'xlf', 'application/x-xpinstall' => 'xpi', 'application/x-xz' => 'xz', + 'application/x-zip-compressed' => 'zip', 'application/x-zmachine' => 'z1', 'application/xaml+xml' => 'xaml', 'application/xcap-diff+xml' => 'xdf', From bc1b652b171fcdb6085ba0ffc7544552d5f9ff55 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Tue, 30 Jan 2018 22:23:40 +0100 Subject: [PATCH 44/68] Added a README entry to the PR template --- .github/PULL_REQUEST_TEMPLATE.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e51cf88761451..f52d3571ceb93 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,8 +11,10 @@ | Doc PR | symfony/symfony-docs#... From b32fdf1ca3ae87098876a761b1cf128852842517 Mon Sep 17 00:00:00 2001 From: Greg Anderson Date: Mon, 12 Feb 2018 14:05:44 -0800 Subject: [PATCH 45/68] Fixes #26136: Avoid emitting warning in hasParameterOption() --- src/Symfony/Component/Console/Input/ArgvInput.php | 4 ++-- .../Console/Tests/Input/ArgvInputTest.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index da064598d0741..62c658b4f9c6a 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -283,7 +283,7 @@ public function hasParameterOption($values) // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ($token === $value || 0 === strpos($token, $leading)) { + if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { return true; } } @@ -311,7 +311,7 @@ public function getParameterOption($values, $default = false) // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if (0 === strpos($token, $leading)) { + if ('' !== $leading && 0 === strpos($token, $leading)) { return substr($token, strlen($leading)); } } diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 04f5ce3157c44..c2a277a93fa78 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -337,6 +337,21 @@ public function testHasParameterOptionEdgeCasesAndLimitations() $this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); } + public function testNoWarningOnInvalidParameterOption() + { + $input = new ArgvInput(array('cli.php', '-edev')); + + // Control. + $this->assertTrue($input->hasParameterOption(array('-e', ''))); + // No warning is thrown if https://github.com/symfony/symfony/pull/26156 is fixed + $this->assertFalse($input->hasParameterOption(array('-m', ''))); + + // Control. + $this->assertEquals('dev', $input->getParameterOption(array('-e', ''))); + // No warning is thrown if https://github.com/symfony/symfony/pull/26156 is fixed + $this->assertFalse($input->getParameterOption(array('-m', ''))); + } + public function testToString() { $input = new ArgvInput(array('cli.php', '-f', 'foo')); From 800cadfb82fd072e75b88f0cca3be6207b9c3263 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 16 Feb 2018 06:42:51 +0100 Subject: [PATCH 46/68] removed extra-verbose comments --- src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index c2a277a93fa78..5f813ee39fa60 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -341,14 +341,12 @@ public function testNoWarningOnInvalidParameterOption() { $input = new ArgvInput(array('cli.php', '-edev')); - // Control. $this->assertTrue($input->hasParameterOption(array('-e', ''))); - // No warning is thrown if https://github.com/symfony/symfony/pull/26156 is fixed + // No warning thrown $this->assertFalse($input->hasParameterOption(array('-m', ''))); - // Control. $this->assertEquals('dev', $input->getParameterOption(array('-e', ''))); - // No warning is thrown if https://github.com/symfony/symfony/pull/26156 is fixed + // No warning thrown $this->assertFalse($input->getParameterOption(array('-m', ''))); } From 43f942159d05eebdb88efb28a606ea3b07eaac68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Klva=C4=8D?= Date: Sun, 18 Feb 2018 14:02:56 +0100 Subject: [PATCH 47/68] Suppress warning from sapi_windows_vt100_support on stream other than STDIO --- src/Symfony/Component/Console/Output/StreamOutput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index d32b1cfb54cae..d36e6f9560159 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -90,7 +90,7 @@ protected function hasColorSupport() { if (DIRECTORY_SEPARATOR === '\\') { return - function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->stream) + function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support($this->stream) || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') From 0e4d26a5688f3b0292e12fdfa32815c37969159e Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Sun, 18 Feb 2018 18:35:19 +0100 Subject: [PATCH 48/68] Improve the documentation of --- src/Symfony/Component/Filesystem/Filesystem.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 575ebaac4adb1..5c3b2a2d9cb8e 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -431,13 +431,18 @@ public function makePathRelative($endPath, $startPath) /** * Mirrors a directory to another. * + * Copies files and directories from the origin directory into the target directory. By default: + * + * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) + * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) + * * @param string $originDir The origin directory * @param string $targetDir The target directory - * @param \Traversable $iterator A Traversable instance + * @param \Traversable $iterator Iterator that filters which files and directories to copy * @param array $options An array of boolean options * Valid options are: - * - $options['override'] Whether to override an existing file on copy or not (see copy()) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) + * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown From 7490f0b0606255e1b60a13ef82f57017e585d3d4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 19 Feb 2018 12:59:32 +0100 Subject: [PATCH 49/68] [HttpFoundation] Fix missing "throw" in JsonResponse --- src/Symfony/Component/HttpFoundation/JsonResponse.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 4ec2fa19a0f47..51852443c115c 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -148,6 +148,7 @@ public function setData($data = array()) if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) { restore_error_handler(); } + throw $e; } catch (\Exception $e) { if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) { restore_error_handler(); From 9ff86d61810a62fe69fd1671f8a8bb325d95468e Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Sat, 16 Dec 2017 16:19:00 +0100 Subject: [PATCH 50/68] [WebProfilerBundle] limit ajax request to 100 and remove the last one --- .../Resources/views/Profiler/base_js.html.twig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index cde7a4c685832..7aae3eef5bbcf 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -108,6 +108,11 @@ var rows = document.createDocumentFragment(); if (requestStack.length) { + var nbOfAjaxRequest = tbodies.rows.count(); + if (nbOfAjaxRequest >= 100) { + tbodies.deleteRow(nbOfAjaxRequest - 1); + } + for (var i = 0; i < requestStack.length; i++) { var request = requestStack[i]; From 4055224373e321b63879873376257fe0efe07f26 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 19 Feb 2018 15:59:04 +0100 Subject: [PATCH 51/68] Clean calls to http_build_query() --- src/Symfony/Component/DomCrawler/Form.php | 2 +- src/Symfony/Component/HttpFoundation/Request.php | 2 +- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 2 +- .../Component/Security/Http/Firewall/SwitchUserListener.php | 2 +- .../Component/Security/Http/Logout/LogoutUrlGenerator.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 54e5fc2b84a3a..258be960a707d 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -209,7 +209,7 @@ public function getUri() parse_str($query, $currentParameters); } - $queryString = http_build_query(array_merge($currentParameters, $this->getValues()), null, '&'); + $queryString = http_build_query(array_merge($currentParameters, $this->getValues()), '', '&'); $pos = strpos($uri, '?'); $base = false === $pos ? $uri : substr($uri, 0, $pos); diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index fe7080ab86321..ecdcdbc25acc2 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -522,7 +522,7 @@ public function __toString() */ public function overrideGlobals() { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&'))); + $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); $_GET = $this->query->all(); $_POST = $this->request->all(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 96f87958ed9c5..0c5451dfd6ccc 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -2065,7 +2065,7 @@ class RequestContentProxy extends Request { public function getContent($asResource = false) { - return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent')); + return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'), '', '&'); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index f5113aa0c90ad..05531d8837ba0 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -89,7 +89,7 @@ public function handle(GetResponseEvent $event) } $request->query->remove($this->usernameParameter); - $request->server->set('QUERY_STRING', http_build_query($request->query->all())); + $request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&')); $response = new RedirectResponse($request->getUri(), 302); diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 1499d7e5ea33f..28ff315505796 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -128,7 +128,7 @@ private function generateLogoutUrl($key, $referenceType) $url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBaseUrl().$logoutPath; if (!empty($parameters)) { - $url .= '?'.http_build_query($parameters); + $url .= '?'.http_build_query($parameters, '', '&'); } } else { if (!$this->router) { From 270147b04fbf54a688f4532c4d552d4d2041ee22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 19 Feb 2018 17:05:09 +0100 Subject: [PATCH 52/68] [PropertyInfo] ReflectionExtractor: give a chance to other extractors if no properties --- .../Extractor/ReflectionExtractor.php | 2 +- .../Extractors/ReflectionExtractorTest.php | 2 ++ .../Tests/Fixtures/NoProperties.php | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/NoProperties.php diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 3ec1d8d6eab08..b29d78d070108 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -76,7 +76,7 @@ public function getProperties($class, array $context = array()) $properties[$propertyName] = $propertyName; } - return array_values($properties); + return $properties ? array_values($properties) : null; } /** diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index cc2ecbe6f56d2..2828878ce6cf0 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -57,6 +57,8 @@ public function testGetProperties() ), $this->extractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy') ); + + $this->assertNull($this->extractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\NoProperties')); } /** diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/NoProperties.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/NoProperties.php new file mode 100644 index 0000000000000..177bbe4df0f03 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/NoProperties.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +/** + * @author Kévin Dunglas + */ +class NoProperties +{ +} From c338d85514a1fb84a616c8af259fdfb13c4fb54f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 20 Feb 2018 13:42:18 +0100 Subject: [PATCH 53/68] Another PR template tweak --- .github/PULL_REQUEST_TEMPLATE.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f52d3571ceb93..2d64894f413fe 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,15 +3,15 @@ | Branch? | master for features / 2.7 up to 4.0 for bug fixes | Bug fix? | yes/no | New feature? | yes/no -| BC breaks? | yes/no +| BC breaks? | no | Deprecations? | yes/no -| Tests pass? | yes/no -| Fixed tickets | #... +| Tests pass? | yes +| Fixed tickets | #... | License | MIT -| Doc PR | symfony/symfony-docs#... +| Doc PR | symfony/symfony-docs#...