diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e51cf88761451..2d64894f413fe 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,16 +3,18 @@ | 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#... diff --git a/.travis.yml b/.travis.yml index 2a3e945695143..25ca170da93a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ cache: directories: - .phpunit - php-$MIN_PHP + - ~/php-ext services: mongodb @@ -100,10 +101,26 @@ 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 + # tpecl is a helper to compile and cache php extensions + tpecl () { + local ext_name=$1 + local ext_so=$2 + local INI=$3 + 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 @@ -122,11 +139,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 $INI + tfold ext.apcu tpecl apcu-4.0.11 apcu.so $INI elif [[ ! $skip && $PHP = 7.* ]]; then - tfold ext.apcu5 'echo yes | pecl install -f apcu-5.1.6' + tfold ext.apcu tpecl apcu-5.1.6 apcu.so $INI + tfold ext.mongodb tpecl mongodb-1.4.0RC1 mongodb.so $INI fi install: 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) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index c4b5466e54e3c..239dbb5c839c2 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,33 @@ in 2.8 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.8.0...v2.8.1 +* 2.8.35 (2018-03-01) + + * bug #26338 [Debug] Keep previous errors of Error instances (Philipp91) + * bug #26312 [Routing] Don't throw 405 when scheme requirement doesn't match (nicolas-grekas) + * bug #26298 Fix ArrayInput::toString() for InputArgument::IS_ARRAY args (maximium) + * bug #26236 [PropertyInfo] ReflectionExtractor: give a chance to other extractors if no properties (dunglas) + * bug #25557 [WebProfilerBundle] add a way to limit ajax request (Simperfit) + * bug #26228 [HttpFoundation] Fix missing "throw" in JsonResponse (nicolas-grekas) + * bug #26211 [Console] Suppress warning from sapi_windows_vt100_support (adawolfa) + * bug #26156 Fixes #26136: Avoid emitting warning in hasParameterOption() (greg-1-anderson) + * bug #26183 [DI] Add null check for removeChild (changmin.keum) + * bug #26173 [Security] fix accessing request values (xabbuh) + * bug #26159 created validator.tl.xlf for Form/Translations (ergiegonzaga) + * bug #26100 [Routing] Throw 405 instead of 404 when redirect is not possible (nicolas-grekas) + * bug #26040 [Process] Check PHP_BINDIR before $PATH in PhpExecutableFinder (nicolas-grekas) + * bug #26012 Exit as late as possible (greg0ire) + * bug #26111 [Security] fix merge of 2.7 into 2.8 + add test case (dmaicher) + * bug #25893 [Console] Fix hasParameterOption / getParameterOption when used with multiple flags (greg-1-anderson) + * bug #25940 [Form] keep the context when validating forms (xabbuh) + * bug #25373 Use the PCRE_DOLLAR_ENDONLY modifier in route regexes (mpdude) + * bug #26010 [CssSelector] For AND operator, the left operand should have parentheses, not only right operand (Arnaud CHASSEUX) + * bug #25971 [Debug] Fix bad registration of exception handler, leading to mem leak (nicolas-grekas) + * bug #25962 [Routing] Fix trailing slash redirection for non-safe verbs (nicolas-grekas) + * bug #25948 [Form] Fixed empty data on expanded ChoiceType and FileType (HeahDude) + * bug #25972 support sapi_windows_vt100_support for php 7.2+ (jhdxr) + * bug #25744 [TwigBridge] Allow label translation to be safe (MatTheCat) + * 2.8.34 (2018-01-29) * bug #25922 [HttpFoundation] Use the correct syntax for session gc based on Pdo driver (tanasecosminromeo) 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) diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index 05c9b402b6bfd..f9524e7710f16 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -127,8 +127,14 @@ UPGRADE FROM 2.x to 3.0 $table->render(); ``` +* Parameters of `renderException()` method of the + `Symfony\Component\Console\Application` are type hinted. + You must add the type hint to your implementations. + ### DependencyInjection + * The method `remove` was added to `Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface`. + * The concept of scopes was removed, the removed methods are: - `Symfony\Component\DependencyInjection\ContainerBuilder::getScopes()` @@ -211,6 +217,22 @@ UPGRADE FROM 2.x to 3.0 removed: `ContainerBuilder::synchronize()`, `Definition::isSynchronized()`, and `Definition::setSynchronized()`. +### DomCrawler + + * The interface of the `Symfony\Component\DomCrawler\Crawler` changed. It does no longer implement `\Iterator` but `\IteratorAggregate`. If you rely on methods of the `\Iterator` interface, call the `getIterator` method of the `\IteratorAggregate` interface before. No changes are required in a `\Traversable`-aware control structure, such as `foreach`. + + Before: + + ```php + $crawler->current(); + ``` + + After: + + ```php + $crawler->getIterator()->current(); + ``` + ### DoctrineBridge * The `property` option of `DoctrineType` was removed in favor of the `choice_label` option. @@ -236,11 +258,22 @@ UPGRADE FROM 2.x to 3.0 ### EventDispatcher + * The method `getListenerPriority($eventName, $listener)` has been added to the + `EventDispatcherInterface`. * The interface `Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface` extends `Symfony\Component\EventDispatcher\EventDispatcherInterface`. ### Form + * The `getBlockPrefix()` method was added to the `FormTypeInterface` in replacement of + the `getName()` method which has been removed. + + * The `configureOptions()` method was added to the `FormTypeInterface` in replacement + of the `setDefaultOptions()` method which has been removed. + + * The `getBlockPrefix()` method was added to the `ResolvedFormTypeInterface` in + replacement of the `getName()` method which has been removed. + * The option `options` of the `CollectionType` has been removed in favor of the `entry_options` option. @@ -380,8 +413,8 @@ UPGRADE FROM 2.x to 3.0 $form = $this->createForm(MyType::class); ``` - * Passing custom data to forms now needs to be done - through the options resolver. + * Passing custom data to forms now needs to be done + through the options resolver. In the controller: @@ -392,7 +425,7 @@ UPGRADE FROM 2.x to 3.0 'method' => 'PUT', )); ``` - After: + After: ```php $form = $this->createForm(MyType::class, $entity, array( 'action' => $this->generateUrl('action_route'), @@ -401,13 +434,13 @@ UPGRADE FROM 2.x to 3.0 )); ``` In the form type: - + Before: ```php class MyType extends AbstractType { private $value; - + public function __construct($variableValue) { $this->value = $value; @@ -415,7 +448,7 @@ UPGRADE FROM 2.x to 3.0 // ... } ``` - + After: ```php public function buildForm(FormBuilderInterface $builder, array $options) @@ -423,7 +456,7 @@ UPGRADE FROM 2.x to 3.0 $value = $options['custom_value']; // ... } - + public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( @@ -431,7 +464,7 @@ UPGRADE FROM 2.x to 3.0 )); } ``` - + * The alias option of the `form.type_extension` tag was removed in favor of the `extended_type`/`extended-type` option. @@ -690,6 +723,11 @@ UPGRADE FROM 2.x to 3.0 be removed in Symfony 3.0. Use the `debug:config`, `debug:container`, `debug:router`, `debug:translation` and `lint:yaml` commands instead. + * The base `Controller`class is now abstract. + + * The visibility of all methods of the base `Controller` class has been changed from + `public` to `protected`. + * The `getRequest` method of the base `Controller` class has been deprecated since Symfony 2.4 and must be therefore removed in 3.0. The only reliable way to get the `Request` object is to inject it in the action method. @@ -816,6 +854,8 @@ UPGRADE FROM 2.x to 3.0 * The `RouterApacheDumperCommand` was removed. + * The `createEsi` method of `Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache` was removed. Use `createSurrogate` instead. + * The `templating.helper.router` service was moved to `templating_php.xml`. You have to ensure that the PHP templating engine is enabled to be able to use it: @@ -1009,6 +1049,12 @@ UPGRADE FROM 2.x to 3.0 ### Security + * The `vote()` method from the `VoterInterface` was changed to now accept arbitrary + types and not only objects. You can rely on the new abstract `Voter` class introduced + in 2.8 to ease integrating your own voters. + + * The `AbstractVoter` class was removed in favor of the new `Voter` class. + * The `Resources/` directory was moved to `Core/Resources/` * The `key` settings of `anonymous`, `remember_me` and `http_digest` are @@ -1206,6 +1252,68 @@ UPGRADE FROM 2.x to 3.0 * The `Translator::setFallbackLocale()` method has been removed in favor of `Translator::setFallbackLocales()`. + * The visibility of the `locale` property has been changed from protected to private. Rely on `getLocale` and `setLocale` + instead. + + Before: + + ```php + class CustomTranslator extends Translator + { + public function fooMethod() + { + // get locale + $locale = $this->locale; + + // update locale + $this->locale = $locale; + } + } + ``` + + After: + + ```php + class CustomTranslator extends Translator + { + public function fooMethod() + { + // get locale + $locale = $this->getLocale(); + + // update locale + $this->setLocale($locale); + } + } + ``` + + * The method `FileDumper::format()` was removed. You should use + `FileDumper::formatCatalogue()` instead. + + Before: + + ```php + class CustomDumper extends FileDumper + { + protected function format(MessageCatalogue $messages, $domain) + { + ... + } + } + ``` + + After: + + ```php + class CustomDumper extends FileDumper + { + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array()) + { + ... + } + } + ``` + * The `getMessages()` method of the `Symfony\Component\Translation\Translator` class was removed. You should use the `getCatalogue()` method of the `Symfony\Component\Translation\TranslatorBagInterface`. @@ -1768,8 +1876,23 @@ UPGRADE FROM 2.x to 3.0 `Process::setInput()` and `Process::getInput()` that works the same way. * `Process::setInput()` and `ProcessBuilder::setInput()` do not accept non-scalar types. +### Monolog Bridge + + * `Symfony\Bridge\Monolog\Logger::emerg()` was removed. Use `emergency()` which is PSR-3 compatible. + * `Symfony\Bridge\Monolog\Logger::crit()` was removed. Use `critical()` which is PSR-3 compatible. + * `Symfony\Bridge\Monolog\Logger::err()` was removed. Use `error()` which is PSR-3 compatible. + * `Symfony\Bridge\Monolog\Logger::warn()` was removed. Use `warning()` which is PSR-3 compatible. + +### Swiftmailer Bridge + + * `Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector` was removed. Use the `Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector` class instead. + ### HttpFoundation + * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" + + * `Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface` no longer implements the `IteratorAggregate` interface. Use the `all()` method instead of iterating over the flash bag. + * Removed the feature that allowed finding deep items in `ParameterBag::get()`. This may affect you when getting parameters from the `Request` class: diff --git a/appveyor.yml b/appveyor.yml index 1b0d362ee3f62..e23696c240fc2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,10 +18,10 @@ install: - mkdir c:\php && cd c:\php - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-5.3.9-nts-Win32-VC9-x86.zip - - 7z x php-5.3.9-nts-Win32-VC9-x86.zip -y >nul - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/ICU-51.2-dlls.zip - 7z x ICU-51.2-dlls.zip -y >nul - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip + - 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul - cd ext - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/php_intl-3.0.0-5.3-nts-vc9-x86.zip - 7z x php_intl-3.0.0-5.3-nts-vc9-x86.zip -y >nul @@ -48,19 +48,21 @@ install: - echo extension=php_ldap.dll >> php.ini-max - echo extension=php_curl.dll >> php.ini-max - echo curl.cainfo=c:\php\cacert.pem >> php.ini-max - - copy /Y php.ini-max php.ini + - copy /Y php.ini-min php.ini + - echo extension=php_openssl.dll >> php.ini - cd c:\projects\symfony - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.3.0/composer.phar) - php composer.phar self-update - copy /Y .composer\* %APPDATA%\Composer\ - php .github/build-packages.php "HEAD^" src\Symfony\Bridge\PhpUnit - IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev) + - php composer.phar config platform.php 5.3.9 - php composer.phar update --no-progress --no-suggest --ansi - php phpunit install test_script: - SET X=0 - - cd c:\php && 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul && copy /Y php.ini-min php.ini + - cd c:\php && copy /Y php.ini-min php.ini - cd c:\projects\symfony - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - cd c:\php && 7z x php-5.3.9-nts-Win32-VC9-x86.zip -y >nul && copy /Y php.ini-min php.ini 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; } diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 8bf22d5bfa5be..f0e1818f8554e 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -161,32 +161,53 @@ public static function register($mode = 0) 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"; + } + }; - if (DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) { - exit(1); + $displayDeprecations($deprecations); + + // store failing status + $isFailing = DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']; + + // 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 || DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) { + exit(1); + } + }); }); } } @@ -195,7 +216,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/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 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 50706b65e59d6..e662e09232e50 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 @@ -224,7 +224,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 -%} 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); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index 20c223a135f1c..0bf193d5c5575 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/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 a2a07bc753558..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->any()) - ->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/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 ed0bcca6562eb..25074dfd18b2c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt @@ -1,17 +1,17 @@ -+--------------+---------------------------------------------------------+ -| Property | Value | -+--------------+---------------------------------------------------------+ -| Route Name | | -| Path | /hello/{name} | -| Path Regex | #^/hello(?:/(?P[a-z]+))?$#s | -| Host | localhost | -| Host Regex | #^localhost$#si | -| Scheme | http|https | -| Method | GET|HEAD | -| Requirements | name: [a-z]+ | -| Class | Symfony\Component\Routing\Route | -| Defaults | name: Joseph | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | -+--------------+---------------------------------------------------------+ ++--------------+-------------------------------------------------------------------+ +| Property | Value | ++--------------+-------------------------------------------------------------------+ +| Route Name | | +| Path | /hello/{name} | +| Path Regex | #PATH_REGEX# | +| Host | localhost | +| Host Regex | #HOST_REGEX# | +| Scheme | http|https | +| Method | GET|HEAD | +| Requirements | name: [a-z]+ | +| Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | +| Defaults | name: Joseph | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | ++--------------+-------------------------------------------------------------------+ 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 828f6316bedb9..5593cc0d81ab0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt @@ -1,17 +1,17 @@ -+--------------+---------------------------------------------------------+ -| Property | Value | -+--------------+---------------------------------------------------------+ -| Route Name | | -| Path | /name/add | -| Path Regex | #^/name/add$#s | -| Host | localhost | -| Host Regex | #^localhost$#si | -| Scheme | http|https | -| Method | PUT|POST | -| Requirements | NO CUSTOM | -| Class | Symfony\Component\Routing\Route | -| Defaults | NONE | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | -+--------------+---------------------------------------------------------+ ++--------------+-------------------------------------------------------------------+ +| Property | Value | ++--------------+-------------------------------------------------------------------+ +| Route Name | | +| Path | /name/add | +| Path Regex | #PATH_REGEX# | +| Host | localhost | +| Host Regex | #HOST_REGEX# | +| Scheme | http|https | +| Method | PUT|POST | +| Requirements | NO CUSTOM | +| Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | +| Defaults | NONE | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | ++--------------+-------------------------------------------------------------------+ 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/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/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index cb4fbeed7e2cb..b861911a372c1 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 @@ -50,7 +50,7 @@ setTimeout(function(){ options.maxTries--; request(url, onSuccess, onError, payload, options); - }, 500); + }, 1000); return null; } @@ -111,6 +111,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]; diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index ee0bd2c128aa6..42147fef9cfe8 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -281,7 +281,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 || '' !== $leading && 0 === strpos($token, $leading)) { return true; } } @@ -302,13 +306,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 ('' !== $leading && 0 === strpos($token, $leading)) { + return substr($token, strlen($leading)); + } } } diff --git a/src/Symfony/Component/Console/Input/ArrayInput.php b/src/Symfony/Component/Console/Input/ArrayInput.php index c4c12c83fbde2..2d69a964af3e1 100644 --- a/src/Symfony/Component/Console/Input/ArrayInput.php +++ b/src/Symfony/Component/Console/Input/ArrayInput.php @@ -106,7 +106,7 @@ public function __toString() $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); } } else { - $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val); + $params[] = is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val); } } diff --git a/src/Symfony/Component/Console/Input/InputInterface.php b/src/Symfony/Component/Console/Input/InputInterface.php index 02d985dbcc93d..805ee5173652d 100644 --- a/src/Symfony/Component/Console/Input/InputInterface.php +++ b/src/Symfony/Component/Console/Input/InputInterface.php @@ -33,6 +33,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) * @@ -45,6 +47,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/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index 51cad9b176a08..324323be2723d 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -92,7 +92,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/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 1fe21d0f6c1a8..5f813ee39fa60 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,46 @@ 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 testNoWarningOnInvalidParameterOption() + { + $input = new ArgvInput(array('cli.php', '-edev')); + + $this->assertTrue($input->hasParameterOption(array('-e', ''))); + // No warning thrown + $this->assertFalse($input->hasParameterOption(array('-m', ''))); + + $this->assertEquals('dev', $input->getParameterOption(array('-e', ''))); + // No warning thrown + $this->assertFalse($input->getParameterOption(array('-m', ''))); + } + public function testToString() { $input = new ArgvInput(array('cli.php', '-f', 'foo')); @@ -327,6 +371,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'), diff --git a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php index 608020a5caa55..b998172e62816 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php @@ -143,5 +143,8 @@ public function testToString() $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2'))); $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input); + + $input = new ArrayInput(array('array_arg' => array('val_1', 'val_2'))); + $this->assertSame('val_1 val_2', (string) $input); } } 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 ')]"), diff --git a/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php b/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php index 60c5a426fdfbc..f8ba536d10bba 100644 --- a/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php +++ b/src/Symfony/Component/CssSelector/Tests/CssSelectorTest.php @@ -51,7 +51,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 fa59bce2e0bb5..63e3ac36bf820 100644 --- a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php +++ b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php @@ -59,7 +59,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; } @@ -103,7 +103,7 @@ public function addStarPrefix() * * @return $this */ - public function join($combiner, XPathExpr $expr) + public function join($combiner, self $expr) { $path = $this->__toString().$combiner; diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 8736fd344a6d1..ace6ea4cb8e6a 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -151,9 +151,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/Exception/FatalThrowableError.php b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php index 34f43b17b13b4..fafc92263e704 100644 --- a/src/Symfony/Component/Debug/Exception/FatalThrowableError.php +++ b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php @@ -36,7 +36,8 @@ public function __construct(\Throwable $e) $e->getCode(), $severity, $e->getFile(), - $e->getLine() + $e->getLine(), + $e->getPrevious() ); $this->setTrace($e->getTrace()); diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 410ab6127114c..518239602b1a2 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -35,7 +35,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); 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)), ); } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 129796fb296e8..56627d4279a27 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -152,7 +152,7 @@ public function setFactoryMethod($factoryMethod) */ public function setDecoratedService($id, $renamedId = null, $priority = 0) { - 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)); } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 5f428256b49f1..d2d1ea5ab9137 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -347,7 +347,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); + } } } } 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/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/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/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 0d8836bfbd064..98bd6f9b439f0 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 diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 99a9c633378f3..4d9b470fe1fdc 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -423,6 +423,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 @@ -443,6 +445,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 diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 0a45ad7a49fe6..5e06d54a0ad38 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 9a4ab5eea7c7e..a06f19537ceea 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/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 5cd29b96a9f54..df533d5d3e9bc 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -139,6 +139,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()) @@ -159,6 +160,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/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. + + + + 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 4950dcd287956..cca73972504f7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -699,6 +699,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( @@ -714,6 +729,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( @@ -729,6 +774,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( @@ -744,6 +804,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 */ 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 83b7c8e245f77..11f9985b45729 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -53,6 +53,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() 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', diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 3d4f01982c9cf..d3695d1535c4c 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(); diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 8339e495109b0..dec3d2fcf6af1 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; @@ -216,13 +216,13 @@ class Request ); /** - * @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) { @@ -234,13 +234,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) { @@ -303,13 +303,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 */ @@ -531,7 +531,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 d27189483e51e..0de758c1cd6b4 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -2031,11 +2031,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() @@ -2114,7 +2114,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/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f2db06634cca4..df4421a131bad 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,11 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.34'; - const VERSION_ID = 20834; + const VERSION = '2.8.35'; + const VERSION_ID = 20835; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 34; + const RELEASE_VERSION = 35; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; 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'); } } 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 --------- diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index fb297825fe364..4bc27fe4d4574 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.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { + return $php; + } + $dirs = array(PHP_BINDIR); if ('\\' === DIRECTORY_SEPARATOR) { $dirs[] = 'C:\xampp\php\\'; diff --git a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php index 8009fc0bb10a4..bdec97c4d7942 100644 --- a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php +++ b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php @@ -114,7 +114,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'); } } } 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/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) + { + } } 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 +{ +} diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 016021e259c5f..8701dfd304a4f 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 @@ -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,52 +258,82 @@ 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]'; + + if ($hasTrailingSlash) { + $code .= <<context->getMethod(), array('HEAD', 'GET'))) { goto $gotoname; + } else { + return \$this->redirect(\$rawPathinfo.'/', '$name'); } EOF; - } else { + } + + if ($schemes = $route->getSchemes()) { + if (!$supportsRedirections) { + throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); + } + $schemes = str_replace("\n", '', var_export(array_flip($schemes), true)); + if ($methods) { $methods = implode("', '", $methods); $code .= <<context->getScheme()]); if (!in_array(\$this->context->getMethod(), array('$methods'))) { - \$allow = array_merge(\$allow, array('$methods')); + if (\$hasRequiredScheme) { + \$allow = array_merge(\$allow, array('$methods')); + } goto $gotoname; } + if (!\$hasRequiredScheme) { + if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) { + goto $gotoname; + } + + return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)); + } EOF; - } - } + } else { + $code .= <<context->getScheme()])) { + if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) { + goto $gotoname; + } - if ($hasTrailingSlash) { - $code .= <<redirect(\$rawPathinfo.'/', '$name'); + return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)); } EOF; - } - - if ($schemes = $route->getSchemes()) { - if (!$supportsRedirections) { - throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); } - $schemes = str_replace("\n", '', var_export(array_flip($schemes), true)); - $code .= <<context->getScheme()])) { - return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)); + } elseif ($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 @@ -329,7 +359,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } $code .= " }\n"; - if ($methods) { + if ($hasTrailingSlash || $schemes || $methods) { $code .= " $gotoname:\n"; } diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 1ef92827dccb9..e2b9f14710777 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -129,6 +129,12 @@ protected function matchCollection($pathinfo, RouteCollection $routes) continue; } + $status = $this->handleRouteRequirements($pathinfo, $name, $route); + + if (self::REQUIREMENT_MISMATCH === $status[0]) { + continue; + } + // check HTTP method requirement if ($requiredMethods = $route->getMethods()) { // HEAD and GET are equivalent as per RFC @@ -137,22 +143,18 @@ protected function matchCollection($pathinfo, RouteCollection $routes) } if (!in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); + if (self::REQUIREMENT_MATCH === $status[0]) { + $this->allow = array_merge($this->allow, $requiredMethods); + } continue; } } - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - if (self::ROUTE_MATCH === $status[0]) { return $status[1]; } - if (self::REQUIREMENT_MISMATCH === $status[0]) { - continue; - } - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches)); } } diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index 3ae7b4147d134..c80a599d9d79a 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -117,7 +117,7 @@ public function remove($name) * Adds a route collection at the end of the current set by appending all * routes of the added collection. */ - public function addCollection(RouteCollection $collection) + public function addCollection(self $collection) { // we need to remove all routes with the same names first because just replacing them // would not place the new route at the end of the merged array 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 6451192d1877e..5b0703cb7fb84 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -20,16 +20,16 @@ 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)) { + 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 9b44eb920deab..7c8e997477063 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -20,16 +20,16 @@ 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)) { + 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; @@ -66,26 +66,36 @@ 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 (preg_match('#^/test/(?P[^/]++)/?$#sD', $pathinfo, $matches)) { + 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)) { + if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { if ($this->context->getMethod() != 'POST') { $allow[] = 'POST'; goto not_baz5; @@ -96,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; @@ -114,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 ()); } @@ -126,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 ()); } @@ -159,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!',)); } @@ -170,22 +180,27 @@ 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: } // 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 ()); } @@ -196,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 ()); } @@ -204,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'); @@ -217,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'); @@ -225,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'); @@ -233,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'); @@ -246,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) { @@ -259,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',)); } @@ -272,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 ()); } @@ -282,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',)); } @@ -301,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 ()); } @@ -318,21 +333,31 @@ 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'))) { + 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'))) { + 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/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index 04043273df740..09b5876bc9580 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 @@ -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/DumpedRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php new file mode 100644 index 0000000000000..cfbb524d3aa79 --- /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); + 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..880b2b13b1112 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php @@ -0,0 +1,48 @@ + + * + * 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(); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface. + */ + public function testSchemeAndMethodMismatch() + { + parent::testSchemeRequirement(); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + static $i = 0; + + $class = 'DumpedUrlMatcher'.++$i; + $dumper = new PhpMatcherDumper($routes); + 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..e5d189d662ffc 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() + public function testMissingTrailingSlash() { $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') @@ -57,16 +56,15 @@ public function testSchemeRedirectRedirectsToFirstScheme() $matcher->match('/foo'); } - public function testNoSchemaRedirectIfOnOfMultipleSchemesMatches() + public function testNoSchemaRedirectIfOneOfMultipleSchemesMatches() { $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..8328962ae4bd5 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,17 +158,29 @@ 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')); } + /** + * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException + */ + public function testTrailingEncodedNewlineIsNotOverlooked() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $matcher = $this->getUrlMatcher($collection); + $matcher->match('/foo%0a'); + } + 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 +190,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 +204,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 +217,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 +235,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 +244,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 +253,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 +272,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 +287,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 +296,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 +308,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 +320,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 +332,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 +345,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 +355,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 +364,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 +380,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 +389,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 +400,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 +415,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 +427,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 +436,48 @@ 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')); + } + + /** + * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException + */ + public function testSchemeAndMethodMismatch() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/', array(), array(), array(), null, array('https'), array('POST'))); + + $matcher = $this->getUrlMatcher($coll); + $matcher->match('/'); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return new UrlMatcher($routes, $context ?: new RequestContext()); + } } 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+')); diff --git a/src/Symfony/Component/Routing/Tests/RouterTest.php b/src/Symfony/Component/Routing/Tests/RouterTest.php index 409959eec07dc..3e3d43f82cc86 100644 --- a/src/Symfony/Component/Routing/Tests/RouterTest.php +++ b/src/Symfony/Component/Routing/Tests/RouterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Routing\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Router; use Symfony\Component\HttpFoundation\Request; @@ -83,7 +84,7 @@ public function testThatRouteCollectionIsLoaded() { $this->router->setOption('resource_type', 'ResourceType'); - $routeCollection = $this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock(); + $routeCollection = new RouteCollection(); $this->loader->expects($this->once()) ->method('load')->with('routing.yml', 'ResourceType') @@ -101,7 +102,7 @@ public function testMatcherIsCreatedIfCacheIsNotConfigured($option) $this->loader->expects($this->once()) ->method('load')->with('routing.yml', null) - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock())); + ->will($this->returnValue(new RouteCollection())); $this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher()); } @@ -123,7 +124,7 @@ public function testGeneratorIsCreatedIfCacheIsNotConfigured($option) $this->loader->expects($this->once()) ->method('load')->with('routing.yml', null) - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock())); + ->will($this->returnValue(new RouteCollection())); $this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator()); } 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. 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/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))); 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/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/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index c55608ae53812..13748c868e8b6 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) { 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( 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. 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. + + + + 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/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 9de4b3cc83846..a2433d286a46c 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 10ee0a952ae8d..9c0da74adc692 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -47,7 +47,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; } /** @@ -68,14 +68,14 @@ public function normalize($object, $format = null, array $context = array()) $attributes = $this->getAttributes($object, $context); 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)) { @@ -123,8 +123,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 7952a17d97b16..7fa2711918a36 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))); 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). + + + + diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 120023fef2169..ca3ec63f7f7ec 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -448,7 +448,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')