diff --git a/.github/build-packages.php b/.github/build-packages.php new file mode 100644 index 0000000000000..ec629998f600d --- /dev/null +++ b/.github/build-packages.php @@ -0,0 +1,77 @@ + $_SERVER['argc']) { + echo "Usage: branch dir1 dir2 ... dirN\n"; + exit(1); +} +chdir(dirname(__DIR__)); + +$dirs = $_SERVER['argv']; +array_shift($dirs); +$mergeBase = trim(shell_exec(sprintf('git merge-base %s HEAD', array_shift($dirs)))); + +$packages = array(); +$flags = PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; + +foreach ($dirs as $k => $dir) { + if (!system("git diff --name-only $mergeBase -- $dir", $exitStatus)) { + if ($exitStatus) { + exit($exitStatus); + } + unset($dirs[$k]); + continue; + } + echo "$dir\n"; + + $json = ltrim(file_get_contents($dir.'/composer.json')); + if (null === $package = json_decode($json)) { + passthru("composer validate $dir/composer.json"); + exit(1); + } + + $package->repositories = array(array( + 'type' => 'composer', + 'url' => 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__)).'/', + )); + if (false === strpos($json, "\n \"repositories\": [\n")) { + $json = rtrim(json_encode(array('repositories' => $package->repositories), $flags), "\n}").','.substr($json, 1); + file_put_contents($dir.'/composer.json', $json); + } + passthru("cd $dir && tar -cf package.tar --exclude='package.tar' *"); + + if (!isset($package->extra->{'branch-alias'}->{'dev-master'})) { + echo "Missing \"dev-master\" branch-alias in composer.json extra.\n"; + exit(1); + } + $package->version = str_replace('-dev', '.999', $package->extra->{'branch-alias'}->{'dev-master'}); + $package->dist['type'] = 'tar'; + $package->dist['url'] = 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__))."/$dir/package.tar"; + + $packages[$package->name][$package->version] = $package; + + $versions = file_get_contents('https://packagist.org/packages/'.$package->name.'.json'); + $versions = json_decode($versions); + + foreach ($versions->package->versions as $v => $package) { + $packages[$package->name] += array($v => $package); + } +} + +file_put_contents('packages.json', json_encode(compact('packages'), $flags)); + +if ($dirs) { + $json = ltrim(file_get_contents('composer.json')); + if (null === $package = json_decode($json)) { + passthru("composer validate $dir/composer.json"); + exit(1); + } + + $package->repositories = array(array( + 'type' => 'composer', + 'url' => 'file://'.str_replace(DIRECTORY_SEPARATOR, '/', dirname(__DIR__)).'/', + )); + if (false === strpos($json, "\n \"repositories\": [\n")) { + $json = rtrim(json_encode(array('repositories' => $package->repositories), $flags), "\n}").','.substr($json, 1); + file_put_contents('composer.json', $json); + } +} diff --git a/.github/travis.php b/.github/travis.php deleted file mode 100644 index 695c69604fe67..0000000000000 --- a/.github/travis.php +++ /dev/null @@ -1,54 +0,0 @@ - $_SERVER['argc']) { - echo "Usage: branch version dir1 dir2 ... dirN\n"; - exit(1); -} -chdir(dirname(__DIR__)); - -$dirs = $_SERVER['argv']; -array_shift($dirs); -$branch = array_shift($dirs); -$version = array_shift($dirs); - -$packages = array(); -$flags = PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; - -foreach ($dirs as $dir) { - if (!system("git diff --name-only $branch...HEAD -- $dir", $exitStatus)) { - if ($exitStatus) { - exit($exitStatus); - } - continue; - } - echo "$dir\n"; - - $json = ltrim(file_get_contents($dir.'/composer.json')); - if (null === $package = json_decode($json)) { - passthru("composer validate $dir/composer.json"); - exit(1); - } - - $package->repositories = array(array( - 'type' => 'composer', - 'url' => 'file://'.dirname(__DIR__).'/', - )); - $json = rtrim(json_encode(array('repositories' => $package->repositories), $flags), "\n}").','.substr($json, 1); - file_put_contents($dir.'/composer.json', $json); - passthru("cd $dir && tar -cf package.tar --exclude='package.tar' *"); - - $package->version = $version.'.999'; - $package->dist['type'] = 'tar'; - $package->dist['url'] = 'file://'.dirname(__DIR__)."/$dir/package.tar"; - - $packages[$package->name][$package->version] = $package; - - $versions = file_get_contents('https://packagist.org/packages/'.$package->name.'.json'); - $versions = json_decode($versions); - - foreach ($versions->package->versions as $v => $package) { - $packages[$package->name] += array($v => $package); - } -} - -file_put_contents('packages.json', json_encode(compact('packages'), $flags)); diff --git a/.travis.yml b/.travis.yml index f7fbaa300cf8b..bbf7547445fb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,22 +58,27 @@ before_install: - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = ldap.so >> $INI_FILE; fi - if [[ ! $skip && ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi - if [[ ! $skip ]]; then [ -d ~/.composer ] || mkdir ~/.composer; cp .composer/* ~/.composer/; fi - - if [[ ! $skip ]]; then ./phpunit install; fi - if [[ ! $skip ]]; then export PHPUNIT=$(readlink -f ./phpunit); fi install: + - if [[ ! $skip && $deps ]]; then cp composer.json composer.json.orig; fi + - if [[ ! $skip && $deps ]]; then echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json; fi - if [[ ! $skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi # Create local composer packages for each patched components and reference them in composer.json files when cross-testing components - - if [[ ! $skip && $deps ]]; then git fetch origin $TRAVIS_BRANCH && php .github/travis.php FETCH_HEAD $TRAVIS_BRANCH $COMPONENTS; fi + - if [[ ! $skip && $deps ]]; then php .github/build-packages.php HEAD^ $COMPONENTS; fi + - if [[ ! $skip && $deps ]]; then mv composer.json composer.json.phpunit; mv composer.json.orig composer.json; fi + - if [[ ! $skip && ! $deps ]]; then php .github/build-packages.php HEAD^ src/Symfony/Bridge/PhpUnit; fi # For the master branch when deps=high, the version before master is checked out and tested with the locally patched components - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi - - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); ./phpunit install; fi + - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi # Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one - if [[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]]; then LEGACY=,legacy; fi - export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev - - if [[ ! $deps ]]; then composer update; else export SYMFONY_DEPRECATIONS_HELPER=weak; fi - - if [[ $TRAVIS_BRANCH = master ]]; then export SYMFONY_PHPUNIT_OVERLOAD=1; fi - - if [[ ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi + - if [[ ! $skip && $deps ]]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi + - if [[ ! $skip && $deps ]]; then mv composer.json.phpunit composer.json; fi + - if [[ ! $skip ]]; then composer update; fi + - if [[ ! $skip ]]; then COMPOSER_ROOT_VERSION= ./phpunit install; fi + - if [[ ! $skip && ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi script: - if [[ $skip ]]; then echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m"; fi diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index c5f93200d0d51..e05a5f9bf7142 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,31 @@ 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.19 (2016-10-03) + + * bug #20102 [Validator] Url validator not validating hosts ending in a number (gwkunze) + * bug #20132 Use "more entropy" option for uniqid() (javiereguiluz) + * bug #20122 [Validator] Reset constraint options (ro0NL) + * bug #20116 fixed AddConstraintValidatorsPass config (fabpot) + * bug #20078 Fix #19943 Make sure to process each interface metadata only once (lemoinem) + * bug #20080 [Form] compound forms without children should be considered rendered implicitly (backbone87) + * bug #20086 [VarDumper] Fix PHP 7.1 compat (nicolas-grekas) + * bug #20077 [Process] silent file operation to avoid open basedir issues (xabbuh) + * bug #20079 fixed Twig support for 1.26 and 2.0 (fabpot) + * bug #19951 [Finder] Trim trailing directory slash in ExcludeDirectoryFilterIterator (ro0NL) + * bug #20010 [DX] Fixed regression when exception message swallowed when logging it. (Koc) + * bug #19983 [TwigBridge] removed Twig null nodes (deprecated as of Twig 1.25) (fabpot) + * bug #19946 [Console] Fix parsing optionnal options with empty value in argv (chalasr) + * bug #19636 [Finder] no PHP warning on empty directory iteration (ggottwald) + * bug #19923 [bugfix] [Console] Set `Input::$interactive` to `false` when command is executed with `--quiet` as verbosity level (phansys) + * bug #19811 Fixed the nullable support for php 7.1 and below (2.7, 2.8, 3.0) (iltar) + * bug #19904 [Form] Fixed collapsed ChoiceType options attributes (HeahDude) + * bug #19908 [Config] Handle open_basedir restrictions in FileLocator (Nicofuma) + * bug #19922 [Yaml][TwigBridge] Use JSON_UNESCAPED_SLASHES for lint commands output (chalasr) + * bug #19928 [Validator] Update IpValidatorTest data set with a valid reserved IP (jakzal) + * bug #19813 [Console] fixed PHP7 Errors are now handled and converted to Exceptions (fonsecas72) + * bug #19879 [Form] Incorrect timezone with DateTimeLocalizedStringTransformer (mbeccati) + * 2.7.18 (2016-09-07) * bug #19859 [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1) (nicolas-grekas) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7cbed979c4960..b0646cc1303cd 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 - Kris Wallsmith (kriswallsmith) - Jakub Zalas (jakubzalas) - Ryan Weaver (weaverryan) - - Javier Eguiluz (javier.eguiluz) - Kévin Dunglas (dunglas) + - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) - Pascal Borreli (pborreli) @@ -35,8 +35,8 @@ Symfony is the result of the work of many people who made the code better - Eriksen Costa (eriksencosta) - Sarah Khalil (saro0h) - Jules Pietri (heah) - - Jonathan Wage (jwage) - Maxime Steinhausser (ogizanagi) + - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) - Alexandre Salomé (alexandresalome) - William Durand (couac) @@ -49,22 +49,22 @@ Symfony is the result of the work of many people who made the code better - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - Diego Saint Esteben (dii3g0) + - Ener-Getick (energetick) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Ener-Getick (energetick) - Peter Rehm (rpet) - Iltar van der Berg (kjarli) + - Robin Chalas (chalas_r) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) + - Charles Sarrazin (csarrazi) - Matthias Pigulla (mpdude) - Christian Raue - Arnout Boks (aboks) - - Charles Sarrazin (csarrazi) - - Robin Chalas (chalas_r) - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) @@ -72,22 +72,22 @@ Symfony is the result of the work of many people who made the code better - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Graham Campbell (graham) + - Titouan Galopin (tgalopin) - Daniel Holmes (dholmes) - Pierre du Plessis (pierredup) + - Konstantin Myakshin (koc) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - - Graham Campbell (graham) - John Wards (johnwards) - Toni Uebernickel (havvg) - Fran Moreno (franmomu) - Antoine Hérault (herzult) + - Paráda József (paradajozsef) - Arnaud Le Blanc (arnaud-lb) - Jérôme Tamarelle (gromnan) - - Paráda József (paradajozsef) - - Titouan Galopin (tgalopin) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - - Konstantin Myakshin (koc) - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - Dariusz Ruminski @@ -105,6 +105,7 @@ Symfony is the result of the work of many people who made the code better - excelwebzone - Jacob Dreesen (jdreesen) - Jáchym Toušek (enumag) + - Roland Franssen (ro0) - Jérémy DERUSSÉ (jderusse) - Vladimir Reznichenko (kalessil) - Tomáš Votruba (tomas_votruba) @@ -112,6 +113,7 @@ Symfony is the result of the work of many people who made the code better - Gordon Franke (gimler) - Eric GELOEN (gelo) - David Buchmann (dbu) + - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) @@ -123,7 +125,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Sebastiaan Stok (sstok) - - Tugdual Saunier (tucksaun) - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) @@ -133,6 +134,7 @@ Symfony is the result of the work of many people who made the code better - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) - Vyacheslav Pavlov + - Javier Spagnoletti (phansys) - Richard Shank (iampersistent) - Thomas Rabaix (rande) - Vincent AUBERT (vincent) @@ -144,10 +146,10 @@ Symfony is the result of the work of many people who made the code better - Richard van Laak (rvanlaak) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - - Javier Spagnoletti (phansys) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba + - Teoh Han Hui (teohhanhui) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -158,11 +160,12 @@ Symfony is the result of the work of many people who made the code better - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) - Benjamin Dulau (dbenjamin) + - Mathieu Lemoine (lemoinem) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) + - Yonel Ceruto González (yonelceruto) - Stepan Anchugov (kix) - bronze1man - - Roland Franssen (ro0) - sun (sun) - Larry Garfield (crell) - Martin Schuhfuß (usefulthink) @@ -188,14 +191,13 @@ Symfony is the result of the work of many people who made the code better - Dawid Nowak - Eugene Wissner - Julien Brochet (mewt) - - Yonel Ceruto González (yonelceruto) + - jeremyFreeAgent (jeremyfreeagent) - Sergey Linnik (linniksa) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) - Loïc Faugeron - Jannik Zschiesche (apfelbox) - Marco Pivetta (ocramius) - - Teoh Han Hui (teohhanhui) - julien pauli (jpauli) - Michael Lee (zerustech) - Lorenz Schori @@ -216,6 +218,7 @@ Symfony is the result of the work of many people who made the code better - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA + - James Halsall (jaitsu) - Alif Rachmawadi - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) @@ -226,10 +229,10 @@ Symfony is the result of the work of many people who made the code better - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon - - jeremyFreeAgent (jeremyfreeagent) - Jan Sorgalla (jsor) - Ray - Grégoire Paris (greg0ire) + - Leo Feyer - Chekote - Tobias Nyholm (tobias) - Thomas Adam @@ -252,12 +255,14 @@ Symfony is the result of the work of many people who made the code better - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Marc Weistroff (futurecat) + - SpacePossum - Hidde Wieringa (hiddewie) - Chris Smith (cs278) - Florian Klein (docteurklein) - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - Daniel Wehner + - Tristan Darricau (nicofuma) - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) @@ -266,7 +271,6 @@ Symfony is the result of the work of many people who made the code better - Thomas Tourlourat (armetiz) - Andrey Esaulov (andremaha) - Grégoire Passault (gregwar) - - Leo Feyer - Ismael Ambrosi (iambrosi) - Uwe Jäger (uwej711) - Aurelijus Valeiša (aurelijus) @@ -315,14 +319,11 @@ Symfony is the result of the work of many people who made the code better - JhonnyL - hossein zolfi (ocean) - Clément Gautier (clementgautier) - - James Halsall (jaitsu) - Eduardo Gulias (egulias) - giulio de donato (liuggio) - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) - Kirill chEbba Chebunin (chebba) - - Tristan Darricau (nicofuma) - - SpacePossum - Greg Thornton (xdissent) - Costin Bereveanu (schniper) - Loïc Chardonnet (gnusat) @@ -390,13 +391,13 @@ Symfony is the result of the work of many people who made the code better - Christian Schmidt - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) + - Maxime STEINHAUSSER - Marek Pietrzak - Chad Sikorra (chadsikorra) - - Mathieu Lemoine - franek (franek) - Christian Wahler - - Mathieu Lemoine - Gintautas Miselis + - Rob Bast - David Badura (davidbadura) - Zander Baldwin - Adam Harvey @@ -414,6 +415,7 @@ Symfony is the result of the work of many people who made the code better - Sebastian Bergmann - Pablo Díez (pablodip) - Kevin McBride + - Sergio Santoro - Philipp Rieber (bicpi) - Manuel de Ruiter (manuel) - Eduardo Oliveira (entering) @@ -545,10 +547,10 @@ Symfony is the result of the work of many people who made the code better - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) - Antoine Corcy - - Rob Bast - Artur Eshenbrener - Arturs Vonda - Sascha Grossenbacher + - David Maicher (dmaicher) - Szijarto Tamas - Catalin Dan - Stephan Vock @@ -559,9 +561,10 @@ Symfony is the result of the work of many people who made the code better - Tristan Roussel - Cameron Porter - Hossein Bukhamsin + - Oliver Hoff - Disparity - origaminal - - Maxime STEINHAUSSER + - Matteo Beccati (matteobeccati) - Paweł Wacławczyk (pwc) - Oleg Zinchenko (cystbear) - Johannes Klauss (cloppy) @@ -581,7 +584,6 @@ Symfony is the result of the work of many people who made the code better - Michael Piecko - yclian - twifty - - Sergio Santoro - Peter Ward - Dominik Ritter (dritter) - Sebastian Grodzicki (sgrodzicki) @@ -604,6 +606,7 @@ Symfony is the result of the work of many people who made the code better - Andrew Tchircoff (andrewtch) - michaelwilliams - 1emming + - Victor Bocharsky (bocharsky_bw) - Leevi Graham (leevigraham) - Casper Valdemar Poulsen - Josiah (josiah) @@ -651,6 +654,7 @@ Symfony is the result of the work of many people who made the code better - Fabian Vogler (fabian) - Korvin Szanto - Alaattin Kahramanlar (alaattin) + - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) - Neil Ferreira - Nathanael Noblet (gnat) @@ -722,6 +726,7 @@ Symfony is the result of the work of many people who made the code better - Benoît Merlet (trompette) - Koen Kuipers - datibbaw + - Erik Saunier (snickers) - Rootie - Raul Fraile (raulfraile) - sensio @@ -731,6 +736,7 @@ Symfony is the result of the work of many people who made the code better - Mátyás Somfai (smatyas) - stefan.r - Valérian Galliat + - Rikijs Murgs - Alexandru Furculita (afurculita) - Ben Ramsey (ramsey) - Christian Jul Jensen @@ -810,6 +816,7 @@ Symfony is the result of the work of many people who made the code better - Benjamin Paap (benjaminpaap) - Christian - Sergii Smertin (nfx) + - hugofonseca (fonsecas72) - Bailey Parker - Eddie Jaoude - Haritz Iturbe (hizai) @@ -837,7 +844,6 @@ Symfony is the result of the work of many people who made the code better - Rodrigo Díez Villamuera (rodrigodiez) - e-ivanov - Jochen Bayer (jocl) - - Matteo Beccati (matteobeccati) - Jeremy Bush - wizhippo - Viacheslav Sychov @@ -887,7 +893,6 @@ Symfony is the result of the work of many people who made the code better - Christian Sciberras - Clement Herreman (clemherreman) - Dan Ionut Dumitriu (danionut90) - - David Maicher (dmaicher) - Nyro (nyro) - Marco - Marc Torres @@ -983,7 +988,6 @@ Symfony is the result of the work of many people who made the code better - Tadcka - Beth Binkovitz - Romain Geissler - - Oliver Hoff - Tomaz Ahlin - Benjamin Cremer (bcremer) - Marcus Stöhr (dafish) @@ -1012,6 +1016,7 @@ Symfony is the result of the work of many people who made the code better - BilgeXA - r1pp3rj4ck - Robert Queck + - Peter Bouwdewijn - mlively - Amine Matmati - Fabian Steiner (fabstei) @@ -1040,6 +1045,7 @@ Symfony is the result of the work of many people who made the code better - Konrad Mohrfeldt - Lance Chen - Andrey Astakhov (aast) + - Andrew (drew) - Nikolay Labinskiy (e-moe) - kor3k kor3k (kor3k) - Stelian Mocanita (stelian) @@ -1203,7 +1209,6 @@ Symfony is the result of the work of many people who made the code better - J Bruni - Alexey Prilipko - bertillon - - Victor Bocharsky (bocharsky_bw) - Yannick Bensacq (cibou) - Luca Genuzio (genuzio) - Hans Nilsson (hansnilsson) @@ -1236,6 +1241,7 @@ Symfony is the result of the work of many people who made the code better - Julien DIDIER (juliendidier) - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) + - Götz Gottwald - Veres Lajos - grifx - Robert Campbell @@ -1462,8 +1468,8 @@ Symfony is the result of the work of many people who made the code better - Adel ELHAIBA (eadel) - Damián Nohales (eagleoneraptor) - Elliot Anderson (elliot) - - Sergey Zolotov (enleur) - Fabien D. (fabd) + - Fabien Bourigault (fbourigault) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) - Yohan Giarelli (frequence-web) @@ -1498,6 +1504,7 @@ Symfony is the result of the work of many people who made the code better - Paul Andrieux (paulandrieux) - Paweł Szczepanek (pauluz) - Philippe Degeeter (pdegeeter) + - Pedro Miguel Maymone de Resende (pedroresende) - Christian López Espínola (penyaskito) - Petr Jaroš (petajaros) - Philipp Hoffmann (philipphoffmann) @@ -1522,6 +1529,7 @@ Symfony is the result of the work of many people who made the code better - Moritz Kraft (userfriendly) - Víctor Mateo (victormateo) - Vincent (vincent1870) + - Valentin Udaltsov (vudaltsov) - Eugene Babushkin (warl) - Wouter Sioen (wouter_sioen) - Xavier Amado (xamado) @@ -1559,6 +1567,5 @@ Symfony is the result of the work of many people who made the code better - Pierre Geyer (ptheg) - Sam Fleming (sam_fleming) - Thomas BERTRAND (sevrahk) - - Erik Saunier (snickers) - Matej Žilák (teo_sk) - Vladislav Vlastovskiy (vlastv) diff --git a/appveyor.yml b/appveyor.yml index 6e143bf4aba94..adf63a1539493 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,18 +48,20 @@ install: - echo curl.cainfo=c:\php\cacert.pem >> php.ini-max - copy /Y php.ini-max php.ini - cd c:\projects\symfony - - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.2.0/composer.phar) + - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.2.1/composer.phar) - php composer.phar self-update - copy /Y .composer\* %APPDATA%\Composer\ - - php phpunit install + - 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 update --no-progress --ansi + - SET COMPOSER_ROOT_VERSION= + - php phpunit install test_script: - cd c:\projects\symfony - SET X=0 - copy /Y c:\php\php.ini-min c:\php\php.ini - - php phpunit symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! + - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - copy /Y c:\php\php.ini-max c:\php\php.ini - - php phpunit symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! + - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - exit %X% diff --git a/composer.json b/composer.json index 613e53f5aa35e..468b4f5b267f2 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "paragonie/random_compat": "~1.0", "symfony/polyfill-apcu": "~1.1", "symfony/polyfill-mbstring": "~1.1", - "twig/twig": "~1.23|~2.0", + "twig/twig": "~1.26|~2.0", "psr/log": "~1.0" }, "replace": { @@ -78,6 +78,7 @@ "monolog/monolog": "~1.11", "ircmaxell/password-compat": "~1.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0", + "symfony/phpunit-bridge": "~3.2", "egulias/email-validator": "~1.2,>=1.2.1" }, "autoload": { @@ -99,11 +100,6 @@ "**/Tests/" ] }, - "autoload-dev": { - "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "src/Symfony/Bridge/PhpUnit/" - } - }, "minimum-stability": "dev", "extra": { "branch-alias": { diff --git a/phpunit b/phpunit index 22432a093c267..f9243bcbf9e79 100755 --- a/phpunit +++ b/phpunit @@ -1,212 +1,9 @@ #!/usr/bin/env php - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -// Please update when phpunit needs to be reinstalled with fresh deps: -// Cache-Id-Version: 2016-06-29 13:45 UTC - -use Symfony\Component\Process\ProcessUtils; - -error_reporting(-1); -require __DIR__.'/src/Symfony/Component/Process/ProcessUtils.php'; - -// PHPUnit 4.8 does not support PHP 7, while 5.1 requires PHP 5.6+ -$PHPUNIT_VERSION = PHP_VERSION_ID >= 50600 ? '5.1' : '4.8'; -$PHPUNIT_DIR = __DIR__.'/.phpunit'; -$PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php'; -$PHP = ProcessUtils::escapeArgument($PHP); -if ('phpdbg' === PHP_SAPI) { - $PHP .= ' -qrr'; -} - -$COMPOSER = file_exists($COMPOSER = __DIR__.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar`)) - ? $PHP.' '.ProcessUtils::escapeArgument($COMPOSER) - : 'composer'; - -if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__) !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) { - // Build a standalone phpunit without symfony/yaml - - $oldPwd = getcwd(); - @mkdir($PHPUNIT_DIR); - chdir($PHPUNIT_DIR); - if (file_exists("phpunit-$PHPUNIT_VERSION")) { - passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? '(del /S /F /Q %s & rmdir %1$s) >nul': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION")); - } - if (extension_loaded('openssl') && ini_get('allow_url_fopen')) { - stream_copy_to_stream(fopen("https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip", 'rb'), fopen("$PHPUNIT_VERSION.zip", 'wb')); - } else { - @unlink("$PHPUNIT_VERSION.zip"); - passthru("wget https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); - } - $zip = new ZipArchive(); - $zip->open("$PHPUNIT_VERSION.zip"); - $zip->extractTo(getcwd()); - $zip->close(); - chdir("phpunit-$PHPUNIT_VERSION"); - passthru("$COMPOSER remove --no-update phpspec/prophecy"); - passthru("$COMPOSER remove --no-update symfony/yaml"); - if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { - passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); - } - passthru("$COMPOSER require --dev --no-update symfony/phpunit-bridge \">=3.2@dev\""); - passthru("$COMPOSER install --prefer-dist --no-progress --ansi", $exit); - if ($exit) { - exit($exit); - } - file_put_contents('phpunit', <<<'EOPHP' -addPsr4('Symfony\\Bridge\\PhpUnit\\', array('src/Symfony/Bridge/PhpUnit'), true); -} -unset($loader); -Symfony\Bridge\PhpUnit\TextUI\Command::main(); - -EOPHP - ); - chdir('..'); - file_put_contents(".$PHPUNIT_VERSION.md5", md5_file(__FILE__)); - chdir($oldPwd); - -} - -$cmd = array_map('Symfony\Component\Process\ProcessUtils::escapeArgument', $argv); -$exit = 0; - -if (isset($argv[1]) && 'symfony' === $argv[1]) { - array_shift($cmd); -} - -$cmd[0] = sprintf('%s %s --colors=always', $PHP, ProcessUtils::escapeArgument("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit")); -$cmd = str_replace('%', '%%', implode(' ', $cmd)).' %1$s'; - -if ('\\' === DIRECTORY_SEPARATOR) { - $cmd = 'cmd /v:on /d /c "('.$cmd.')%2$s"'; -} else { - $cmd .= '%2$s'; -} - -if (isset($argv[1]) && 'symfony' === $argv[1]) { - // Find Symfony components in plain php for Windows portability - - $oldPwd = getcwd(); - chdir(__DIR__); - $finder = new RecursiveDirectoryIterator('src/Symfony', FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::UNIX_PATHS); - $finder = new RecursiveIteratorIterator($finder); - $finder->setMaxDepth(3); - - $skippedTests = isset($_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS']) ? $_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS'] : false; - $runningProcs = array(); - - foreach ($finder as $file => $fileInfo) { - if ('phpunit.xml.dist' === $file) { - $component = dirname($fileInfo->getPathname()); - - // Run phpunit tests in parallel - - if ($skippedTests) { - putenv("SYMFONY_PHPUNIT_SKIPPED_TESTS=$component/$skippedTests"); - } - - $c = ProcessUtils::escapeArgument($component); - - if ($proc = proc_open(sprintf($cmd, $c, " > $c/phpunit.stdout 2> $c/phpunit.stderr"), array(), $pipes)) { - $runningProcs[$component] = $proc; - } else { - $exit = 1; - echo "\033[41mKO\033[0m $component\n\n"; - } - } - } - chdir($oldPwd); - - // Fixes for colors support on appveyor - // See https://github.com/appveyor/ci/issues/373 - $colorFixes = array( - array("S\033[0m\033[0m\033[36m\033[1mS", "E\033[0m\033[0m\033[31m\033[1mE", "I\033[0m\033[0m\033[33m\033[1mI", "F\033[0m\033[0m\033[41m\033[37mF"), - array("SS", "EE", "II", "FF"), - ); - $colorFixes[0] = array_merge($colorFixes[0], $colorFixes[0]); - $colorFixes[1] = array_merge($colorFixes[1], $colorFixes[1]); - - while ($runningProcs) { - usleep(300000); - $terminatedProcs = array(); - foreach ($runningProcs as $component => $proc) { - $procStatus = proc_get_status($proc); - if (!$procStatus['running']) { - $terminatedProcs[$component] = $procStatus['exitcode']; - unset($runningProcs[$component]); - proc_close($proc); - } - } - - foreach ($terminatedProcs as $component => $procStatus) { - foreach (array('out', 'err') as $file) { - $file = "$component/phpunit.std$file"; - - if ('\\' === DIRECTORY_SEPARATOR) { - $h = fopen($file, 'rb'); - while (false !== $line = fgets($h)) { - echo str_replace($colorFixes[0], $colorFixes[1], preg_replace( - '/(\033\[[0-9]++);([0-9]++m)(?:(.)(\033\[0m))?/', - "$1m\033[$2$3$4$4", - $line - )); - } - fclose($h); - } else { - readfile($file); - } - unlink($file); - } - - // Fail on any individual component failures but ignore some error codes on Windows when APCu is enabled: - // STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409) - // STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005) - // STATUS_HEAP_CORRUPTION (-1073740940/0xC0000374) - if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || !in_array($procStatus, array(-1073740791, -1073741819, -1073740940)))) { - $exit = $procStatus; - echo "\033[41mKO\033[0m $component\n\n"; - } else { - echo "\033[32mOK\033[0m $component\n\n"; - } - } - } -} elseif (!isset($argv[1]) || 'install' !== $argv[1]) { - // Run regular phpunit in a subprocess - - $errFile = tempnam(sys_get_temp_dir(), 'phpunit.stderr.'); - if ($proc = proc_open(sprintf($cmd, '', ' 2> '.ProcessUtils::escapeArgument($errFile)), array(1 => array('pipe', 'w')), $pipes)) { - stream_copy_to_stream($pipes[1], STDOUT); - fclose($pipes[1]); - $exit = proc_close($proc); - - readfile($errFile); - unlink($errFile); - } - - if (!file_exists($component = array_pop($argv))) { - $component = basename(getcwd()); - } - - if ($exit) { - echo "\033[41mKO\033[0m $component\n\n"; - } else { - echo "\033[32mOK\033[0m $component\n\n"; - } +if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) { + echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n"; + exit(1); } - -exit($exit); +putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit'); +require __DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit'; diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 0b98419f16203..6d86bd24d2d1a 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -86,7 +86,7 @@ public function getProxyCandidates() $definitions = array( array(new Definition(__CLASS__), true), array(new Definition('stdClass'), true), - array(new Definition('foo'.uniqid()), false), + array(new Definition(uniqid('foo', true)), false), array(new Definition(), false), ); diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 95d550a058bc3..df603f93fddda 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -109,7 +109,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $template .= fread(STDIN, 1024); } - return $this->display($input, $output, array($this->validate($twig, $template, uniqid('sf_')))); + return $this->display($input, $output, array($this->validate($twig, $template, uniqid('sf_', true)))); } $filesInfo = $this->getFilesInfo($twig, $filenames); @@ -202,7 +202,7 @@ private function displayJson(OutputInterface $output, $filesInfo) } }); - $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)); + $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES : 0)); return min($errors, 1); } diff --git a/src/Symfony/Bridge/Twig/Node/DumpNode.php b/src/Symfony/Bridge/Twig/Node/DumpNode.php index 522497ba655dc..a7c152944618f 100644 --- a/src/Symfony/Bridge/Twig/Node/DumpNode.php +++ b/src/Symfony/Bridge/Twig/Node/DumpNode.php @@ -20,7 +20,12 @@ class DumpNode extends \Twig_Node public function __construct($varPrefix, \Twig_Node $values = null, $lineno, $tag = null) { - parent::__construct(array('values' => $values), array(), $lineno, $tag); + $nodes = array(); + if (null !== $values) { + $nodes['values'] = $values; + } + + parent::__construct($nodes, array(), $lineno, $tag); $this->varPrefix = $varPrefix; } @@ -33,9 +38,7 @@ public function compile(\Twig_Compiler $compiler) ->write("if (\$this->env->isDebug()) {\n") ->indent(); - $values = $this->getNode('values'); - - if (null === $values) { + if (!$this->hasNode('values')) { // remove embedded templates (macros) from the context $compiler ->write(sprintf('$%svars = array();'."\n", $this->varPrefix)) @@ -50,7 +53,7 @@ public function compile(\Twig_Compiler $compiler) ->write("}\n") ->addDebugInfo($this) ->write(sprintf('\Symfony\Component\VarDumper\VarDumper::dump($%svars);'."\n", $this->varPrefix)); - } elseif (1 === $values->count()) { + } elseif (($values = $this->getNode('values')) && 1 === $values->count()) { $compiler ->addDebugInfo($this) ->write('\Symfony\Component\VarDumper\VarDumper::dump(') diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index e598ae104a728..91793771393d8 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -30,7 +30,7 @@ public function compile(\Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write('$this->env->getExtension(\'form\')->renderer->setTheme(') + ->write('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->setTheme(') ->subcompile($this->getNode('form')) ->raw(', ') ->subcompile($this->getNode('resources')) diff --git a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php index 35dcb40b627cb..33865e2f1cb78 100644 --- a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php @@ -25,7 +25,7 @@ public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); $arguments = iterator_to_array($this->getNode('arguments')); - $compiler->write('$this->env->getExtension(\'form\')->renderer->renderBlock('); + $compiler->write('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->renderBlock('); if (isset($arguments[0])) { $compiler->subcompile($arguments[0]); diff --git a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php index 93bba43b4c945..8c42bcd3c2650 100644 --- a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php @@ -19,7 +19,7 @@ class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); - $compiler->raw('$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock('); + $compiler->raw('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock('); preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches); diff --git a/src/Symfony/Bridge/Twig/Node/StopwatchNode.php b/src/Symfony/Bridge/Twig/Node/StopwatchNode.php index 06eeb492728c6..95d755a78cdb0 100644 --- a/src/Symfony/Bridge/Twig/Node/StopwatchNode.php +++ b/src/Symfony/Bridge/Twig/Node/StopwatchNode.php @@ -18,7 +18,7 @@ */ class StopwatchNode extends \Twig_Node { - public function __construct(\Twig_Node $name, $body, \Twig_Node_Expression_AssignName $var, $lineno = 0, $tag = null) + public function __construct(\Twig_Node $name, \Twig_Node $body, \Twig_Node_Expression_AssignName $var, $lineno = 0, $tag = null) { parent::__construct(array('body' => $body, 'name' => $name, 'var' => $var), array(), $lineno, $tag); } @@ -32,11 +32,11 @@ public function compile(\Twig_Compiler $compiler) ->raw(' = ') ->subcompile($this->getNode('name')) ->write(";\n") - ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->start(") + ->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->start(") ->subcompile($this->getNode('var')) ->raw(", 'template');\n") ->subcompile($this->getNode('body')) - ->write("\$this->env->getExtension('stopwatch')->getStopwatch()->stop(") + ->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->stop(") ->subcompile($this->getNode('var')) ->raw(");\n") ; diff --git a/src/Symfony/Bridge/Twig/Node/TransNode.php b/src/Symfony/Bridge/Twig/Node/TransNode.php index af85d8f1858ec..114b38c441123 100644 --- a/src/Symfony/Bridge/Twig/Node/TransNode.php +++ b/src/Symfony/Bridge/Twig/Node/TransNode.php @@ -18,7 +18,21 @@ class TransNode extends \Twig_Node { public function __construct(\Twig_Node $body, \Twig_Node $domain = null, \Twig_Node_Expression $count = null, \Twig_Node_Expression $vars = null, \Twig_Node_Expression $locale = null, $lineno = 0, $tag = null) { - parent::__construct(array('count' => $count, 'body' => $body, 'domain' => $domain, 'vars' => $vars, 'locale' => $locale), array(), $lineno, $tag); + $nodes = array('body' => $body); + if (null !== $domain) { + $nodes['domain'] = $domain; + } + if (null !== $count) { + $nodes['count'] = $count; + } + if (null !== $vars) { + $nodes['vars'] = $vars; + } + if (null !== $locale) { + $nodes['locale'] = $locale; + } + + parent::__construct($nodes, array(), $lineno, $tag); } /** @@ -30,24 +44,23 @@ public function compile(\Twig_Compiler $compiler) { $compiler->addDebugInfo($this); - $vars = $this->getNode('vars'); $defaults = new \Twig_Node_Expression_Array(array(), -1); - if ($vars instanceof \Twig_Node_Expression_Array) { + if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof \Twig_Node_Expression_Array) { $defaults = $this->getNode('vars'); $vars = null; } list($msg, $defaults) = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); - $method = null === $this->getNode('count') ? 'trans' : 'transChoice'; + $method = !$this->hasNode('count') ? 'trans' : 'transChoice'; $compiler - ->write('echo $this->env->getExtension(\'translator\')->getTranslator()->'.$method.'(') + ->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->'.$method.'(') ->subcompile($msg) ; $compiler->raw(', '); - if (null !== $this->getNode('count')) { + if ($this->hasNode('count')) { $compiler ->subcompile($this->getNode('count')) ->raw(', ') @@ -68,13 +81,13 @@ public function compile(\Twig_Compiler $compiler) $compiler->raw(', '); - if (null === $this->getNode('domain')) { + if (!$this->hasNode('domain')) { $compiler->repr('messages'); } else { $compiler->subcompile($this->getNode('domain')); } - if (null !== $this->getNode('locale')) { + if ($this->hasNode('locale')) { $compiler ->raw(', ') ->subcompile($this->getNode('locale')) @@ -98,7 +111,7 @@ protected function compileString(\Twig_Node $body, \Twig_Node_Expression_Array $ foreach ($matches[1] as $var) { $key = new \Twig_Node_Expression_Constant('%'.$var.'%', $body->getLine()); if (!$vars->hasElement($key)) { - if ('count' === $var && null !== $this->getNode('count')) { + if ('count' === $var && $this->hasNode('count')) { $vars->addElement($this->getNode('count'), $key); } else { $varExpr = new \Twig_Node_Expression_Name($var, $body->getLine()); diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index c923df9944c60..3e850350fd144 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -78,7 +78,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) } } } elseif ($node instanceof TransNode) { - if (null === $node->getNode('domain')) { + if (!$node->hasNode('domain')) { $node->setNode('domain', $this->scope->get('domain')); } } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php index 4426a9d3b6666..6e3880d09ed98 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php @@ -75,7 +75,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) // extract trans nodes $this->messages[] = array( $node->getNode('body')->getAttribute('data'), - $this->getReadDomainFromNode($node->getNode('domain')), + $node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : null, ); } @@ -122,12 +122,8 @@ private function getReadDomainFromArguments(\Twig_Node $arguments, $index) * * @return string|null */ - private function getReadDomainFromNode(\Twig_Node $node = null) + private function getReadDomainFromNode(\Twig_Node $node) { - if (null === $node) { - return; - } - if ($node instanceof \Twig_Node_Expression_Constant) { return $node->getAttribute('value'); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 0fadfdabc6e77..f407afdcd6968 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -45,7 +45,7 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -57,7 +57,7 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->setTheme(%s, "tpl1");', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->setTheme(%s, "tpl1");', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index 05b28c947dc71..ad76e25e8ee7a 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -27,7 +27,7 @@ public function testCompileWidget() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\')', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'widget\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -50,7 +50,7 @@ public function testCompileWidgetWithVariables() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -70,7 +70,7 @@ public function testCompileLabelWithLabel() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -92,7 +92,7 @@ public function testCompileLabelWithNullLabel() // Otherwise the default label is overwritten with null. $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -114,7 +114,7 @@ public function testCompileLabelWithEmptyStringLabel() // Otherwise the default label is overwritten with null. $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -133,7 +133,7 @@ public function testCompileLabelWithDefaultLabel() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\')', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -160,7 +160,7 @@ public function testCompileLabelWithAttributes() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -186,7 +186,7 @@ public function testCompileLabelWithLabelAndAttributes() $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -217,7 +217,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNull() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -254,7 +254,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getExtension(\'form\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 26ba94a1bf0bd..032975a8f2897 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -29,7 +29,7 @@ public function testCompileStrict() $this->assertEquals( sprintf( - 'echo $this->env->getExtension(\'translator\')->getTranslator()->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");', + 'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");', $this->getVariableGetterWithoutStrictCheck('var'), $this->getVariableGetterWithStrictCheck('foo') ), diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php index d892fe7303e71..2a9450c885837 100644 --- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php +++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php @@ -82,7 +82,7 @@ public function setPrefix($prefix) protected function extractTemplate($template, MessageCatalogue $catalogue) { - $visitor = $this->twig->getExtension('translator')->getTranslationNodeVisitor(); + $visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor(); $visitor->enable(); $this->twig->parse($this->twig->tokenize($template)); diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index f62708cf97df2..c82e7b8cf4098 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.9", - "twig/twig": "~1.23|~2.0" + "twig/twig": "~1.26|~2.0" }, "require-dev": { "symfony/asset": "~2.7", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 4c12e7d2fca05..b41f5f3479ebe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -156,7 +156,7 @@ private function displayJson(OutputInterface $output, $filesInfo) } }); - $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)); + $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES : 0)); return min($errors, 1); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php index e1e1edc416967..800a32e2f30df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php @@ -28,7 +28,17 @@ public function process(ContainerBuilder $container) $validators[$attributes[0]['alias']] = $id; } - $validators[$container->getDefinition($id)->getClass()] = $id; + $definition = $container->getDefinition($id); + + if (!$definition->isPublic()) { + throw new InvalidArgumentException(sprintf('The service "%s" must be public as it can be lazy-loaded.', $id)); + } + + if ($definition->isAbstract()) { + throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id)); + } + + $validators[$definition->getClass()] = $id; } $container->getDefinition('validator.validator_factory')->replaceArgument(1, $validators); diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 499f39c6c95c0..97f6122ff7bdb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -75,7 +75,7 @@ public function build(ContainerBuilder $container) // but as late as possible to get resolved parameters $container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new TemplatingPass()); - $container->addCompilerPass(new AddConstraintValidatorsPass()); + $container->addCompilerPass(new AddConstraintValidatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new AddValidatorInitializersPass()); $container->addCompilerPass(new AddConsoleCommandPass()); $container->addCompilerPass(new FormPass()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php index 8d2d6d7fd63c3..18f8368dc8065 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php @@ -1,4 +1,3 @@ -id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled" $v): ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php index 0fe47b0908d83..894e7ae3285d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php @@ -93,7 +93,7 @@ public function testMissingControllers($name) try { $parser->parse($name); - $this->fail('->parse() throws a \InvalidArgumentException if the string is in the valid format, but not matching class can be found'); + $this->fail('->parse() throws a \InvalidArgumentException if the class is found but does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->parse() throws a \InvalidArgumentException if the class is found but does not exist'); } @@ -108,7 +108,6 @@ public function getMissingControllersTest() } /** - * @expectedException * @dataProvider getInvalidBundleNameTests */ public function testInvalidBundleName($bundleName, $suggestedBundleName) @@ -117,6 +116,7 @@ public function testInvalidBundleName($bundleName, $suggestedBundleName) try { $parser->parse($bundleName); + $this->fail('->parse() throws a \InvalidArgumentException if the bundle does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->parse() throws a \InvalidArgumentException if the bundle does not exist'); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index f00e09ca3c908..0ca847bc1b80b 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -37,7 +37,7 @@ "symfony/yaml": "~2.0,>=2.0.5", "symfony/expression-language": "~2.6", "doctrine/doctrine-bundle": "~1.2", - "twig/twig": "~1.23|~2.0", + "twig/twig": "~1.26|~2.0", "ircmaxell/password-compat": "~1.0" }, "autoload": { diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php index 21e9a1a25c61d..bf37559b9920c 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php @@ -37,12 +37,12 @@ public function __construct($dateFormat, $intervalFormat, $timezone, $decimals, public function configure(\Twig_Environment $environment) { - $environment->getExtension('core')->setDateFormat($this->dateFormat, $this->intervalFormat); + $environment->getExtension('Twig_Extension_Core')->setDateFormat($this->dateFormat, $this->intervalFormat); if (null !== $this->timezone) { - $environment->getExtension('core')->setTimezone($this->timezone); + $environment->getExtension('Twig_Extension_Core')->setTimezone($this->timezone); } - $environment->getExtension('core')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); + $environment->getExtension('Twig_Extension_Core')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); } } diff --git a/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php b/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php index 1c590f9ac8aa3..4e3b12dae1978 100644 --- a/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php +++ b/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php @@ -34,7 +34,7 @@ public function compile(\Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write("echo \$this->env->getExtension('actions')->renderUri(") + ->write("echo \$this->env->getExtension('Symfony\Bundle\TwigBundle\Extension\ActionsExtension')->renderUri(") ->subcompile($this->getNode('expr')) ->raw(', ') ->subcompile($this->getNode('options')) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php index 610bfa3b58be1..0b04f81af0798 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php @@ -72,7 +72,7 @@ public function __construct($withTemplating) { $this->withTemplating = $withTemplating; - parent::__construct('dev', true); + parent::__construct(($withTemplating ? 'with' : 'without').'_templating', true); } public function getName() @@ -106,7 +106,7 @@ public function registerContainerConfiguration(LoaderInterface $loader) public function getCacheDir() { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/CacheWarmingKernel/cache'; + return sys_get_temp_dir().'/'.Kernel::VERSION.'/CacheWarmingKernel/cache/'.$this->environment; } public function getLogDir() diff --git a/src/Symfony/Bundle/TwigBundle/TwigEngine.php b/src/Symfony/Bundle/TwigBundle/TwigEngine.php index 5cd666a3178e9..3092fe9c5d611 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigEngine.php +++ b/src/Symfony/Bundle/TwigBundle/TwigEngine.php @@ -49,7 +49,7 @@ public function setDefaultEscapingStrategy($strategy) { @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0. Inject the escaping strategy in the Twig_Environment object instead.', E_USER_DEPRECATED); - $this->environment->getExtension('escaper')->setDefaultStrategy($strategy); + $this->environment->getExtension('Twig_Extension_Escaper')->setDefaultStrategy($strategy); } /** diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index c05ebe38e8db3..dfee0d6e8089b 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -19,6 +19,7 @@ "php": ">=5.3.9", "symfony/asset": "~2.7", "symfony/twig-bridge": "~2.7", + "twig/twig": "~1.26|~2.0", "symfony/http-foundation": "~2.5", "symfony/http-kernel": "~2.7" }, @@ -31,7 +32,8 @@ "symfony/routing": "~2.1", "symfony/templating": "~2.1", "symfony/yaml": "~2.3", - "symfony/framework-bundle": "~2.7" + "symfony/framework-bundle": "~2.7", + "doctrine/annotations": "~1.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, diff --git a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php index 515bd926eac0b..327876aeaf1b5 100644 --- a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php +++ b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php @@ -14,8 +14,6 @@ use Symfony\Component\Asset\UrlPackage; use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy; use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy; -use Symfony\Component\Asset\Exception\InvalidArgumentException; -use Symfony\Component\Asset\Exception\LogicException; class UrlPackageTest extends \PHPUnit_Framework_TestCase { @@ -79,7 +77,7 @@ public function getContextConfigs() } /** - * @expectedException LogicException + * @expectedException \Symfony\Component\Asset\Exception\LogicException */ public function testNoBaseUrls() { @@ -87,7 +85,7 @@ public function testNoBaseUrls() } /** - * @expectedException InvalidArgumentException + * @expectedException \Symfony\Component\Asset\Exception\InvalidArgumentException */ public function testWrongBaseUrl() { diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Component/Config/FileLocator.php index c6600c7783760..4816724c8190e 100644 --- a/src/Symfony/Component/Config/FileLocator.php +++ b/src/Symfony/Component/Config/FileLocator.php @@ -57,7 +57,7 @@ public function locate($name, $currentPath = null, $first = true) $filepaths = array(); foreach ($paths as $path) { - if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { + if (@file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 590460ca0de99..b11268ade33bf 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -38,6 +38,7 @@ use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -336,7 +337,7 @@ public function register($name) * Adds an array of command objects. * * If a Command is not enabled it will not be added. - * + * * @param Command[] $commands An array of commands */ public function addCommands(array $commands) @@ -807,6 +808,7 @@ protected function configureIO(InputInterface $input, OutputInterface $output) if (true === $input->hasParameterOption(array('--quiet', '-q'))) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $input->setInteractive(false); } else { if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); @@ -849,17 +851,25 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI if ($event->commandShouldRun()) { try { + $e = null; $exitCode = $command->run($input, $output); - } catch (\Exception $e) { + } catch (\Exception $x) { + $e = $x; + } catch (\Throwable $x) { + $e = new FatalThrowableError($x); + } + if (null !== $e) { $event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - $e = $event->getException(); + if ($e !== $event->getException()) { + $x = $e = $event->getException(); + } $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - throw $e; + throw $x; } } else { $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index f18d6e189970c..119be49170853 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -145,7 +145,10 @@ private function parseLongOption($token) $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { - $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); + if (0 === strlen($value = substr($name, $pos + 1))) { + array_unshift($this->parsed, null); + } + $this->addLongOption(substr($name, 0, $pos), $value); } else { $this->addLongOption($name, null); } @@ -232,7 +235,7 @@ private function addLongOption($name, $value) if (isset($next[0]) && '-' !== $next[0]) { $value = $next; } elseif (empty($next)) { - $value = ''; + $value = null; } else { array_unshift($this->parsed, $next); } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 918200d53cfb3..9d375f6b7b264 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -636,9 +636,11 @@ public function testRun() $tester->run(array('command' => 'list', '--quiet' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); $tester->run(array('command' => 'list', '-q' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); $tester->run(array('command' => 'list', '--verbose' => true)); $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); @@ -949,6 +951,62 @@ public function testRunDispatchesAllEventsWithException() $this->assertContains('before.foo.caught.after.', $tester->getDisplay()); } + /** + * @expectedException \LogicException + * @expectedExceptionMessage caught + */ + public function testRunWithErrorAndDispatcher() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dym')); + $this->assertContains('before.dym.caught.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + public function testRunDispatchesAllEventsWithError() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dym')); + $this->assertContains('before.dym.caught.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + public function testRunWithErrorFailingStatusCode() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dus.'); + + throw new \Error('duserr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dus')); + $this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1'); + } + public function testRunWithDispatcherSkippingCommand() { $application = new Application(); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json index b17b38d8a3ed9..ea695a7deff3e 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json @@ -1 +1,172 @@ -{"commands":[{"name":"help","usage":["help [--xml] [--format FORMAT] [--raw] [--] []"],"description":"Displays help for a command","help":"The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.","definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"list","usage":["list [--xml] [--raw] [--format FORMAT] [--] []"],"description":"Lists commands","help":"The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>","definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]} +{ + "commands": [ + { + "name": "help", + "usage": [ + "help [--xml] [--format FORMAT] [--raw] [--] []" + ], + "description": "Displays help for a command", + "help": "The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.", + "definition": { + "arguments": { + "command_name": { + "name": "command_name", + "is_required": false, + "is_array": false, + "description": "The command name", + "default": "help" + } + }, + "options": { + "xml": { + "name": "--xml", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output help as XML", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command help", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "list", + "usage": [ + "list [--xml] [--raw] [--format FORMAT] [--] []" + ], + "description": "Lists commands", + "help": "The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>", + "definition": { + "arguments": { + "namespace": { + "name": "namespace", + "is_required": false, + "is_array": false, + "description": "The namespace name", + "default": null + } + }, + "options": { + "xml": { + "name": "--xml", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output list as XML", + "default": false + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command list", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + } + } + } + } + ], + "namespaces": [ + { + "id": "_global", + "commands": [ + "help", + "list" + ] + } + ] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json index e47a7a962157a..8ffa222ee6eab 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json @@ -1 +1,354 @@ -{"commands":[{"name":"help","usage":["help [--xml] [--format FORMAT] [--raw] [--] []"],"description":"Displays help for a command","help":"The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.","definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"list","usage":["list [--xml] [--raw] [--format FORMAT] [--] []"],"description":"Lists commands","help":"The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>","definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"}}}},{"name":"descriptor:command1","usage":["descriptor:command1", "alias1", "alias2"],"description":"command 1 description","help":"command 1 help","definition":{"arguments":[],"options":{"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"descriptor:command2","usage":["descriptor:command2 [-o|--option_name] [--] ", "descriptor:command2 -o|--option_name ", "descriptor:command2 "],"description":"command 2 description","help":"command 2 help","definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}}],"namespaces":[{"id":"_global","commands":["alias1","alias2","help","list"]},{"id":"descriptor","commands":["descriptor:command1","descriptor:command2"]}]} \ No newline at end of file +{ + "commands": [ + { + "name": "help", + "usage": [ + "help [--xml] [--format FORMAT] [--raw] [--] []" + ], + "description": "Displays help for a command", + "help": "The help<\/info> command displays help for a given command:\n\n php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the --format<\/comment> option:\n\n php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the list<\/info> command.", + "definition": { + "arguments": { + "command_name": { + "name": "command_name", + "is_required": false, + "is_array": false, + "description": "The command name", + "default": "help" + } + }, + "options": { + "xml": { + "name": "--xml", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output help as XML", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command help", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "list", + "usage": [ + "list [--xml] [--raw] [--format FORMAT] [--] []" + ], + "description": "Lists commands", + "help": "The list<\/info> command lists all commands:\n\n php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the --format<\/comment> option:\n\n php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n php app\/console list --raw<\/info>", + "definition": { + "arguments": { + "namespace": { + "name": "namespace", + "is_required": false, + "is_array": false, + "description": "The namespace name", + "default": null + } + }, + "options": { + "xml": { + "name": "--xml", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output list as XML", + "default": false + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command list", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + } + } + } + }, + { + "name": "descriptor:command1", + "usage": [ + "descriptor:command1", + "alias1", + "alias2" + ], + "description": "command 1 description", + "help": "command 1 help", + "definition": { + "arguments": [], + "options": { + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "descriptor:command2", + "usage": [ + "descriptor:command2 [-o|--option_name] [--] ", + "descriptor:command2 -o|--option_name ", + "descriptor:command2 " + ], + "description": "command 2 description", + "help": "command 2 help", + "definition": { + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + } + ], + "namespaces": [ + { + "id": "_global", + "commands": [ + "alias1", + "alias2", + "help", + "list" + ] + }, + { + "id": "descriptor", + "commands": [ + "descriptor:command1", + "descriptor:command2" + ] + } + ] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_1.json b/src/Symfony/Component/Console/Tests/Fixtures/command_1.json index 20f310b457eb0..4cd37eeb4b1f6 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_1.json @@ -1 +1,14 @@ -{"name":"descriptor:command1","usage":["descriptor:command1", "alias1", "alias2"],"description":"command 1 description","help":"command 1 help","definition":{"arguments":[],"options":[]}} +{ + "name": "descriptor:command1", + "usage": [ + "descriptor:command1", + "alias1", + "alias2" + ], + "description": "command 1 description", + "help": "command 1 help", + "definition": { + "arguments": [], + "options": [] + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.json b/src/Symfony/Component/Console/Tests/Fixtures/command_2.json index 38edd1e2098db..74c1f1260424e 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.json @@ -1 +1,32 @@ -{"name":"descriptor:command2","usage":["descriptor:command2 [-o|--option_name] [--] ", "descriptor:command2 -o|--option_name ", "descriptor:command2 "],"description":"command 2 description","help":"command 2 help","definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}} +{ + "name": "descriptor:command2", + "usage": [ + "descriptor:command2 [-o|--option_name] [--] ", + "descriptor:command2 -o|--option_name ", + "descriptor:command2 " + ], + "description": "command 2 description", + "help": "command 2 help", + "definition": { + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json index b8173b6b3fca9..0ab932960164c 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null} +{ + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json index ef06b09a7550f..7450016ffa01c 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_2.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":false,"is_array":true,"description":"argument description","default":[]} +{ + "name": "argument_name", + "is_required": false, + "is_array": true, + "description": "argument description", + "default": [] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json index de8484e6a72ce..9a83c5a544db5 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":false,"is_array":false,"description":"argument description","default":"default_value"} +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "default_value" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.json index 8067a4d1b1279..cbcb19b392b75 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_4.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":true,"is_array":false,"description":"multiline argument description","default":null} +{ + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "multiline argument description", + "default": null +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json index c7a7d838fd5ae..44aa2c2e16ab4 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json @@ -1 +1,4 @@ -{"arguments":[],"options":[]} +{ + "arguments": [], + "options": [] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json index 9964a55ae31ec..7cfd57e56c4bf 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json @@ -1 +1,12 @@ -{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":[]} +{ + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": [] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json index 6a86056029784..3b3cf73c5941d 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json @@ -1 +1,14 @@ -{"arguments":[],"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}} +{ + "arguments": [], + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json index c5a0019fe2a1f..d4a51e82eb4c8 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json @@ -1 +1,22 @@ -{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}} +{ + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json index 60c5b56cb44ea..f86bf9671ced3 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_1.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json index 04e4228ec3164..32dbab21aea86 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_2.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":false,"description":"option description","default":"default_value"} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": false, + "description": "option description", + "default": "default_value" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json index c1ea120c7a24a..6d55a6efeb46b 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_3.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option description","default":null} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "option description", + "default": null +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json index 1b671d80651ef..788a8ed435087 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_4.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":true,"description":"option description","default":[]} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": true, + "description": "option description", + "default": [] +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.json index 35a1405fa436d..9f34d8321db22 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_5.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"multiline option description","default":null} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "multiline option description", + "default": null +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_6.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_6.json index d84e8721475ff..0638de03e0b1f 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_6.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_6.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o|-O","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option with multiple shortcuts","default":null} +{ + "name": "--option_name", + "shortcut": "-o|-O", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "option with multiple shortcuts", + "default": null +} diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 3b0dc3f231659..06347c87ba807 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php @@ -71,6 +71,18 @@ public function provideOptions() array('foo' => 'bar'), '->parse() parses long options with a required value (with a space separator)', ), + array( + array('cli.php', '--foo='), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), + array('foo' => null), + '->parse() parses long options with optional value which is empty (with a = separator) as null', + ), + array( + array('cli.php', '--foo=', 'bar'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), + array('foo' => null), + '->parse() parses long options with optional value which is empty (with a = separator) followed by an argument', + ), array( array('cli.php', '-f'), array(new InputOption('foo', 'f')), @@ -324,4 +336,30 @@ public function testParseSingleDashAsArgument() $input->bind(new InputDefinition(array(new InputArgument('file')))); $this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument'); } + + public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument() + { + $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); + $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); + + $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); + $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); + } + + public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument() + { + $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); + $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); + + $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); + $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); + } } diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index b68129ddfc7e5..1bd4af63cb06e 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -16,7 +16,8 @@ } ], "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/debug": "~2.7,>=2.7.2" }, "require-dev": { "symfony/event-dispatcher": "~2.1", diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index b7bb3c4f31310..3f5a5dfeb133c 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -35,6 +35,7 @@ public function __construct(\Iterator $iterator, array $directories) $this->isRecursive = $iterator instanceof \RecursiveIterator; $patterns = array(); foreach ($directories as $directory) { + $directory = rtrim($directory, '/'); if (!$this->isRecursive || false !== strpos($directory, '/')) { $patterns[] = preg_quote($directory, '#'); } else { @@ -51,7 +52,7 @@ public function __construct(\Iterator $iterator, array $directories) /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool True if the value should be kept, false otherwise */ public function accept() { diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index 402033a5c2816..1df2f5014f622 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -137,6 +137,11 @@ public function isRewindable() return $this->rewindable; } + // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed + if ('' === $this->getPath()) { + return $this->rewindable = false; + } + if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php index c5f4ba495a7ca..fa192c31f4dec 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php @@ -58,9 +58,23 @@ public function getAcceptData() 'foo bar', ); + $toto = array( + '.bar', + '.foo', + '.foo/.bar', + '.foo/bar', + '.git', + 'test.py', + 'foo', + 'foo/bar.tmp', + 'test.php', + 'foo bar', + ); + return array( array(array('foo'), $this->toAbsolute($foo)), array(array('fo'), $this->toAbsolute($fo)), + array(array('toto/'), $this->toAbsolute($toto)), ); } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 51f692755eb6d..d2e5ddba5cd9d 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -134,7 +134,10 @@ public function reverseTransform($value) } // read timestamp into DateTime object - the formatter delivers a timestamp - $dateTime = new \DateTime(sprintf('@%s', $timestamp), new \DateTimeZone($this->outputTimezone)); + $dateTime = new \DateTime(sprintf('@%s', $timestamp)); + // set timezone separately, as it would be ignored if set via the constructor, + // see http://php.net/manual/en/datetime.construct.php + $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php index 4992833e4bda3..401288cf83d91 100644 --- a/src/Symfony/Component/Form/FormView.php +++ b/src/Symfony/Component/Form/FormView.php @@ -65,23 +65,17 @@ public function __construct(FormView $parent = null) */ public function isRendered() { - $hasChildren = 0 < count($this->children); - - if (true === $this->rendered || !$hasChildren) { + if (true === $this->rendered || 0 === count($this->children)) { return $this->rendered; } - if ($hasChildren) { - foreach ($this->children as $child) { - if (!$child->isRendered()) { - return false; - } + foreach ($this->children as $child) { + if (!$child->isRendered()) { + return false; } - - return $this->rendered = true; } - return false; + return $this->rendered = true; } /** diff --git a/src/Symfony/Component/Form/PreloadedExtension.php b/src/Symfony/Component/Form/PreloadedExtension.php index 65519f83d493e..871e8b3791bc9 100644 --- a/src/Symfony/Component/Form/PreloadedExtension.php +++ b/src/Symfony/Component/Form/PreloadedExtension.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\InvalidArgumentException; /** - * A form extension with preloaded types, type exceptions and type guessers. + * A form extension with preloaded types, type extensions and type guessers. * * @author Bernhard Schussek */ diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 01b3d3757a597..6441c07f6bf39 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -612,8 +612,8 @@ public function testSingleChoiceAttributesWithMainAttributes() [@class="bar&baz"] [not(@required)] [ - ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] - /following-sibling::option[@value="&b"][not(@class)][not(@selected)][.="[trans]Choice&B[/trans]"] + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"][not(@id)][not(@name)] + /following-sibling::option[@value="&b"][not(@class)][not(@selected)][.="[trans]Choice&B[/trans]"][not(@id)][not(@name)] ] [count(./option)=2] ' diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index 444cdd4582330..d5abfe7047b5f 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -134,6 +134,23 @@ public function testTransformWithDifferentTimezones() $this->assertEquals($dateTime->format('d.m.Y, H:i'), $transformer->transform($input)); } + public function testReverseTransformWithNoConstructorParameters() + { + $tz = date_default_timezone_get(); + date_default_timezone_set('Europe/Rome'); + + $transformer = new DateTimeToLocalizedStringTransformer(); + + $dateTime = new \DateTime('2010-02-03 04:05'); + + $this->assertEquals( + $dateTime->format('c'), + $transformer->reverseTransform('03.02.2010, 04:05')->format('c') + ); + + date_default_timezone_set($tz); + } + public function testTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index 75e4a20e2a8d5..bd023ed16579d 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -37,8 +37,8 @@ protected function setUp() parent::setUp(); - if (version_compare(phpversion('memcached'), '2.2.0', '>=')) { - $this->markTestSkipped('Tests can only be run with memcached extension 2.1.0 or lower'); + if (version_compare(phpversion('memcached'), '2.2.0', '>=') && version_compare(phpversion('memcached'), '3.0.0b1', '<')) { + $this->markTestSkipped('Tests can only be run with memcached extension 2.1.0 or lower, or 3.0.0b1 or higher'); } $this->memcached = $this->getMock('Memcached'); diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 1d7c49607dfe9..c76b57bb6a7db 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -27,6 +27,15 @@ class ControllerResolver implements ControllerResolverInterface { private $logger; + /** + * If the ...$arg functionality is available. + * + * Requires at least PHP 5.6.0 or HHVM 3.9.1 + * + * @var bool + */ + private $supportsVariadic; + /** * Constructor. * @@ -35,6 +44,8 @@ class ControllerResolver implements ControllerResolverInterface public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; + + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); } /** @@ -99,13 +110,20 @@ public function getArguments(Request $request, $controller) return $this->doGetArguments($request, $controller, $r->getParameters()); } + /** + * @param Request $request + * @param callable $controller + * @param \ReflectionParameter[] $parameters + * + * @return array The arguments to use when calling the action + */ protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); $arguments = array(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { - if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) { + if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { $arguments = array_merge($arguments, array_values($attributes[$param->name])); } else { $arguments[] = $attributes[$param->name]; @@ -114,6 +132,8 @@ protected function doGetArguments(Request $request, $controller, array $paramete $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); + } elseif ($param->allowsNull()) { + $arguments[] = null; } else { if (is_array($controller)) { $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 6664a3373748d..79568d618c0a9 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -147,6 +147,10 @@ private function sanitizeContext($context) } if (is_object($context)) { + if ($context instanceof \Exception) { + return sprintf('Exception(%s): %s', get_class($context), $context->getMessage()); + } + return sprintf('Object(%s)', get_class($context)); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e0e79545193b2..6d86705c87442 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,11 +58,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.18'; - const VERSION_ID = 20718; + const VERSION = '2.7.19'; + const VERSION_ID = 20719; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 18; + const RELEASE_VERSION = 19; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 101782e49079e..9aa7e20a9a910 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -13,6 +13,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; @@ -222,6 +223,34 @@ public function testCreateControllerCanReturnAnyCallable() $mock->getController($request); } + /** + * @requires PHP 7.1 + */ + public function testGetNullableArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('bar', new \stdClass()); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + + /** + * @requires PHP 7.1 + */ + public function testGetNullableArgumentsWithDefaults() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array(null, null, 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + protected function createControllerResolver(LoggerInterface $logger = null) { return new ControllerResolver($logger); diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 18824635ea44f..68d28cf2d211a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -87,19 +87,17 @@ public function testCollectHtml() $file = __FILE__; if (PHP_VERSION_ID >= 50400) { $xOutput = <<DumpDataCollectorTest.php on line {$line}: +
DumpDataCollectorTest.php on line {$line}:
 123
 
- EOTXT; } else { $len = strlen("DumpDataCollectorTest.php on line {$line}:"); $xOutput = <<"DumpDataCollectorTest.php on line {$line}:" +
"DumpDataCollectorTest.php on line {$line}:"
 
123
 
- EOTXT; } @@ -111,7 +109,7 @@ public function testCollectHtml() $output = preg_replace('#<(script|style).*?#s', '', $output); $output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output); - $this->assertSame($xOutput, $output); + $this->assertSame($xOutput, trim($output)); $this->assertSame(1, $collector->getDumpsCount()); $collector->serialize(); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php new file mode 100644 index 0000000000000..9db4df7b4c173 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; + +class NullableController +{ + public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory) + { + } +} diff --git a/src/Symfony/Component/Process/ExecutableFinder.php b/src/Symfony/Component/Process/ExecutableFinder.php index 3bf711149dfab..824457ce2a122 100644 --- a/src/Symfony/Component/Process/ExecutableFinder.php +++ b/src/Symfony/Component/Process/ExecutableFinder.php @@ -79,7 +79,7 @@ public function find($name, $default = null, array $extraDirs = array()) } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { - if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) { + if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) { return $file; } } diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf new file mode 100644 index 0000000000000..33c48c617461c --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf @@ -0,0 +1,71 @@ + + + + + + An authentication exception occurred. + Radās autentifikācijas kļūda. + + + Authentication credentials could not be found. + Autentifikācijas dati nav atrasti. + + + Authentication request could not be processed due to a system problem. + Autentifikācijas pieprasījums nevar tikt apstrādāts sistēmas problēmas dēļ. + + + Invalid credentials. + Nederīgi autentifikācijas dati. + + + Cookie has already been used by someone else. + Kāds cits jau izmantoja sīkdatni. + + + Not privileged to request the resource. + Nav tiesību ši resursa izsaukšanai. + + + Invalid CSRF token. + Nederīgs CSRF talons. + + + Digest nonce has expired. + Vienreiz lietojamās atslēgas darbības laiks ir beidzies. + + + No authentication provider found to support the authentication token. + Nav atrasts, autentifikācijas talonu atbalstošs, autentifikācijas sniedzējs. + + + No session available, it either timed out or cookies are not enabled. + Sesija nav pieejama - vai nu tā beidzās, vai nu sīkdatnes nav iespējotas. + + + No token could be found. + Nevar atrast nevienu talonu. + + + Username could not be found. + Nevar atrast lietotājvārdu. + + + Account has expired. + Konta derīguma termiņš ir beidzies. + + + Credentials have expired. + Autentifikācijas datu derīguma termiņš ir beidzies. + + + Account is disabled. + Konts ir atspējots. + + + Account is locked. + Konts ir slēgts. + + + + \ No newline at end of file diff --git a/src/Symfony/Component/Security/Resources/translations/security.lv.xlf b/src/Symfony/Component/Security/Resources/translations/security.lv.xlf new file mode 100644 index 0000000000000..33c48c617461c --- /dev/null +++ b/src/Symfony/Component/Security/Resources/translations/security.lv.xlf @@ -0,0 +1,71 @@ + + + + + + An authentication exception occurred. + Radās autentifikācijas kļūda. + + + Authentication credentials could not be found. + Autentifikācijas dati nav atrasti. + + + Authentication request could not be processed due to a system problem. + Autentifikācijas pieprasījums nevar tikt apstrādāts sistēmas problēmas dēļ. + + + Invalid credentials. + Nederīgi autentifikācijas dati. + + + Cookie has already been used by someone else. + Kāds cits jau izmantoja sīkdatni. + + + Not privileged to request the resource. + Nav tiesību ši resursa izsaukšanai. + + + Invalid CSRF token. + Nederīgs CSRF talons. + + + Digest nonce has expired. + Vienreiz lietojamās atslēgas darbības laiks ir beidzies. + + + No authentication provider found to support the authentication token. + Nav atrasts, autentifikācijas talonu atbalstošs, autentifikācijas sniedzējs. + + + No session available, it either timed out or cookies are not enabled. + Sesija nav pieejama - vai nu tā beidzās, vai nu sīkdatnes nav iespējotas. + + + No token could be found. + Nevar atrast nevienu talonu. + + + Username could not be found. + Nevar atrast lietotājvārdu. + + + Account has expired. + Konta derīguma termiņš ir beidzies. + + + Credentials have expired. + Autentifikācijas datu derīguma termiņš ir beidzies. + + + Account is disabled. + Konts ir atspējots. + + + Account is locked. + Konts ir slēgts. + + + + \ No newline at end of file diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index a6d06472c2cf3..08041d4c7eed1 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -129,6 +129,9 @@ public function __construct($options = null) unset($options['value']); } + if (is_array($options)) { + reset($options); + } if (is_array($options) && count($options) > 0 && is_string(key($options))) { foreach ($options as $option => $value) { if (array_key_exists($option, $knownOptions)) { diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 3f114fa335fa2..401f7d8bdd648 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -25,13 +25,13 @@ class UrlValidator extends ConstraintValidator (%s):// # protocol (([\pL\pN-]+:)?([\pL\pN-]+)@)? # basic auth ( - ([\pL\pN\pS-\.])+(\.?([\pL]|xn\-\-[\pL\pN-]+)+\.?) # a domain name - | # or - \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # a IP address - | # or + ([\pL\pN\pS-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name + | # or + \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address + | # or \[ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) - \] # a IPv6 address + \] # an IPv6 address ) (:[0-9]+)? # a port (optional) (/?|/\S+|\?\S*|\#\S*) # a /, nothing, a / with something, a query or a fragment diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index b5b202de6d2b6..68236fc1eb069 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -116,9 +116,27 @@ public function getMetadataFor($value) $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } - // Include constraints from all implemented interfaces that have not been processed via parent class yet - foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { - if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name || ($parent && $parent->implementsInterface($interface->name))) { + $interfaces = $metadata->getReflectionClass()->getInterfaces(); + + $interfaces = array_filter($interfaces, function ($interface) use ($parent, $interfaces) { + $interfaceName = $interface->getName(); + + if ($parent && $parent->implementsInterface($interfaceName)) { + return false; + } + + foreach ($interfaces as $i) { + if ($i !== $interface && $i->implementsInterface($interfaceName)) { + return false; + } + } + + return true; + }); + + // Include constraints from all directly implemented interfaces + foreach ($interfaces as $interface) { + if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } $metadata->mergeConstraints($this->getMetadataFor($interface->name)); diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf new file mode 100644 index 0000000000000..2ad19cd283c18 --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf @@ -0,0 +1,315 @@ + + + + + + This value should be false. + Šai vērtībai ir jābūt nepatiesai. + + + This value should be true. + Šai vērtībai ir jābūt patiesai. + + + This value should be of type {{ type }}. + Šīs vērtības tipam ir jābūt {{ type }}. + + + This value should be blank. + Šai vērtībai ir jābūt tukšai. + + + The value you selected is not a valid choice. + Vērtība, kuru jūs izvēlējāties nav derīga izvēle. + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + Jums nav jāveic izvēle.|Jums ir jāveic vismaz {{ limit }} izvēle.|Jums ir jāveic vismaz {{ limit }} izvēles. + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + Jums nav jāveic izvēle.|Jums ir jāveic ne vairāk kā {{ limit }} izvēle.|Jums ir jāveic ne vairāk kā {{ limit }} izvēles. + + + One or more of the given values is invalid. + Viena vai vairākas no dotajām vērtībām ir nederīgas. + + + This field was not expected. + Šis lauks netika gaidīts. + + + This field is missing. + Šis lauks ir pazudis. + + + This value is not a valid date. + Šī vērtība ir nederīgs datums. + + + This value is not a valid datetime. + Šī vērtība ir nederīgs datums un laiks + + + This value is not a valid email address. + Šī vērtība ir nederīga e-pasta adrese. + + + The file could not be found. + Fails nav atrasts. + + + The file is not readable. + Fails nav lasāms. + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + Fails ir pārāk liels ({{ size }} {{ suffix }}). Atļautais maksimālais izmērs ir {{ limit }} {{ suffix }}. + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + Faila mime tips nav derīgs ({{ type }}). Atļautie mime tipi ir {{ types }}. + + + This value should be {{ limit }} or less. + Šai vērtībai ir jābūt ne vairāk kā {{ limit }}. + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + Šīs vērtības garums ir 0 rakstzīmju.|Šī vērtība ir pārāk gara. Tai būtu jābūt ne vairāk kā {{ limit }} rakstzīmei.|Šī vērtība ir pārāk gara. Tai būtu jābūt ne vairāk kā {{ limit }} rakstzīmēm. + + + This value should be {{ limit }} or more. + Šai vērtībai ir jābūt ne mazāk kā {{ limit }}. + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + Šīs vērtības garums ir 0 rakstzīmju.|Šī vērtība ir pārāk īsa. Tai būtu jābūt ne mazāk kā {{ limit }} rakstzīmei.|Šī vērtība ir pārāk īsa. Tai būtu jābūt ne mazāk kā {{ limit }} rakstzīmēm. + + + This value should not be blank. + Šai vērtībai nav jābūt tukšai. + + + This value should not be null. + Šai vērtībai nav jābūt null. + + + This value should be null. + Šai vērtībai ir jābūt null. + + + This value is not valid. + Šī vērtība ir nederīga. + + + This value is not a valid time. + Šī vērtība ir nederīgs laiks. + + + This value is not a valid URL. + Šī vērtība ir nederīgs URL. + + + The two values should be equal. + Abām vērtībām jābūt vienādam. + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + Fails ir pārāk liels. Atļautais maksimālais izmērs ir {{ limit }} {{ suffix }}. + + + The file is too large. + Fails ir pārāk liels. + + + The file could not be uploaded. + Failu nevarēja augšupielādēt. + + + This value should be a valid number. + Šai vērtībai ir jābūt derīgam skaitlim. + + + This file is not a valid image. + Šis fails nav derīgs attēls. + + + This is not a valid IP address. + Šī nav derīga IP adrese. + + + This value is not a valid language. + Šī vērtība nav derīga valoda. + + + This value is not a valid locale. + Šī vērtība nav derīga lokalizācija. + + + This value is not a valid country. + Šī vērtība nav derīga valsts. + + + This value is already used. + Šī vērtība jau tiek izmantota. + + + The size of the image could not be detected. + Nevar noteikt attēla izmēru. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Attēla platums ir pārāk liels ({{ width }}px). Atļautais maksimālais platums ir {{ max_width }}px. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Attēla platums ir pārāk mazs ({{ width }}px). Minimālais sagaidāmais platums ir {{ min_width }}px. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Attēla augstums ir pārāk liels ({{ height }}px). Atļautais maksimālais augstums ir {{ max_height }}px. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Attēla augstums ir pārāk mazs ({{ height }}px). Minimālais sagaidāmais augstums ir {{ min_height }}px. + + + This value should be the user's current password. + Šai vērtībai ir jābūt lietotāja pašreizējai parolei. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Šīs vērtības garums ir 0 rakstzīmju.|Šai vērtībai ir jābūt tieši {{ limit }} rakstzīmei.|Šai vērtībai ir jābūt tieši {{ limit }} rakstzīmēm. + + + The file was only partially uploaded. + Fails bija tikai daļēji augšupielādēts. + + + No file was uploaded. + Fails netika augšupielādēts. + + + No temporary folder was configured in php.ini. + Pagaidu mape php.ini failā nav nokonfigurēta. + + + Cannot write temporary file to disk. + Nevar ierakstīt pagaidu failu uz diska. + + + A PHP extension caused the upload to fail. + PHP paplašinājums izraisīja augšupielādes neizdošanos. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Šis krājums satur 0 elementu.|Šim krājumam jāsatur vismaz {{ limit }} elementu.|Šim krājumam jāsatur vismaz {{ limit }} elementus. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Šis krājums satur 0 elementu.|Šim krājumam jāsatur ne vairāk kā {{ limit }} elementu.|Šim krājumam jāsatur ne vairāk kā {{ limit }} elementus. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Šis krājums satur 0 elementu.|Šim krājumam jāsatur tieši {{ limit }} elementu.|Šim krājumam jāsatur tieši {{ limit }} elementus. + + + Invalid card number. + Nederīgs kartes numurs. + + + Unsupported card type or invalid card number. + Neatbalstīts kartes tips vai nederīgs kartes numurs. + + + This is not a valid International Bank Account Number (IBAN). + Šis nav derīgs starptautisks banku konta numurs (IBAN). + + + This value is not a valid ISBN-10. + Šī vērtība nav derīgs ISBN-10 numurs. + + + This value is not a valid ISBN-13. + Šī vērtība nav derīgs ISBN-13 numurs + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Šī vērtība neatbilst ne derīgam ISBN-10 numuram, ne derīgm ISBN-13 numuram. + + + This value is not a valid ISSN. + Šī vērtība nav derīgs ISSN numurs + + + This value is not a valid currency. + Šī vērtība nav derīga valūta + + + This value should be equal to {{ compared_value }}. + Šai vērtībai ir jābūt vienādai ar {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Šai vērtībai ir jābūt lielākai par {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Šai vērtībai ir jābūt lielākai vai vienādai ar {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Šai vērtībai ir jābūt identiskai ar {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Šai vērtībai ir jābūt mazākai par {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + TŠai vērtībai ir jābūt mazākai vai vienādai ar {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Šai vērtībai ir jābūt vienādai ar {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Šai vērtībai nav jābūt identiskai ar {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Attēla attiecība ir pārāk liela ({{ ratio }}). Atļautā maksimālā attiecība ir {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Attēla attiecība ir pārāk maza ({{ ratio }}). Minimālā sagaidāmā attiecība ir {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Šis attēls ir kvadrāts ({{ width }}x{{ height }}px). Kvadrātveida attēli nav atļauti. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Attēls ir orientēts kā ainava ({{ width }}x{{ height }}px). Attēli, kas ir orientēti kā ainavas nav atļauti. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Attēls ir orientēts kā portrets ({{ width }}x{{ height }}px). Attēli, kas ir orientēti kā portreti nav atļauti. + + + An empty file is not allowed. + Tukšs fails nav atļauts. + + + The host could not be resolved. + Resursdatora nosaukumu nevar atrisināt. + + + This value does not match the expected {{ charset }} charset. + Šī vērtība neatbilst sagaidāmajai rakstzīmju kopai {{ charset }}. + + + + diff --git a/src/Symfony/Component/Validator/Tests/ConstraintTest.php b/src/Symfony/Component/Validator/Tests/ConstraintTest.php index f63570c5d2944..d473f14f651ac 100644 --- a/src/Symfony/Component/Validator/Tests/ConstraintTest.php +++ b/src/Symfony/Component/Validator/Tests/ConstraintTest.php @@ -206,4 +206,35 @@ public function testGetErrorNameForUnknownCode() { Constraint::getErrorName(1); } + + public function testOptionsAsDefaultOption() + { + $constraint = new ConstraintA($options = array('value1')); + + $this->assertEquals($options, $constraint->property2); + + $constraint = new ConstraintA($options = array('value1', 'property1' => 'value2')); + + $this->assertEquals($options, $constraint->property2); + } + + /** + * @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException + * @expectedExceptionMessage The options "0", "5" do not exist + */ + public function testInvalidOptions() + { + new ConstraintA(array('property2' => 'foo', 'bar', 5 => 'baz')); + } + + public function testOptionsWithInvalidInternalPointer() + { + $options = array('property1' => 'foo'); + next($options); + next($options); + + $constraint = new ConstraintA($options); + + $this->assertEquals('foo', $constraint->property1); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php index fc40e6104e14b..2c5dea549b71f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php @@ -218,7 +218,7 @@ public function getInvalidReservedIpsV4() { return array( array('0.0.0.0'), - array('224.0.0.1'), + array('240.0.0.1'), array('255.255.255.255'), ); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index 62d53af8a09a1..98494c66bf361 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -90,6 +90,7 @@ public function getValidUrls() array('http://www.symfony.com/doc/current/book/validation.html#supported-constraints'), array('http://very.long.domain.name.com/'), array('http://localhost/'), + array('http://myhost123/'), array('http://127.0.0.1/'), array('http://127.0.0.1:80/'), array('http://[::1]/'), diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php index e4eec6be32eb1..77a86108a1ae0 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php @@ -19,7 +19,7 @@ * @Assert\GroupSequence({"Foo", "Entity"}) * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"}) */ -class Entity extends EntityParent +class Entity extends EntityParent implements EntityInterfaceB { /** * @Assert\NotNull diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceA.php similarity index 91% rename from src/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php rename to src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceA.php index 2901f26386b4e..a0afcf8163110 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceA.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Validator\Tests\Fixtures; -interface EntityInterface +interface EntityInterfaceA { } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceB.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceB.php new file mode 100644 index 0000000000000..93b389414fadf --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityInterfaceB.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +interface EntityInterfaceB extends EntityParentInterface +{ +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php index acbec3d32e88b..4674f8b35a226 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php @@ -13,7 +13,7 @@ use Symfony\Component\Validator\Constraints\NotNull; -class EntityParent implements EntityInterface +class EntityParent implements EntityInterfaceA { protected $firstName; private $internal; diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParentInterface.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParentInterface.php new file mode 100644 index 0000000000000..3aad6fec5f76e --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityParentInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +interface EntityParentInterface +{ +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index c78d2a72c8d60..c1aaa9f8c7bf2 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -18,17 +18,19 @@ class LazyLoadingMetadataFactoryTest extends \PHPUnit_Framework_TestCase { - const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; - const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; - const INTERFACECLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterface'; + const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; + const PARENT_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; + const INTERFACE_A_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA'; + const INTERFACE_B_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB'; + const PARENT_INTERFACE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParentInterface'; public function testLoadClassMetadataWithInterface() { $factory = new LazyLoadingMetadataFactory(new TestLoader()); - $metadata = $factory->getMetadataFor(self::PARENTCLASS); + $metadata = $factory->getMetadataFor(self::PARENT_CLASS); $constraints = array( - new ConstraintA(array('groups' => array('Default', 'EntityInterface', 'EntityParent'))), + new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA', 'EntityParent'))), new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); @@ -38,12 +40,12 @@ public function testLoadClassMetadataWithInterface() public function testMergeParentConstraints() { $factory = new LazyLoadingMetadataFactory(new TestLoader()); - $metadata = $factory->getMetadataFor(self::CLASSNAME); + $metadata = $factory->getMetadataFor(self::CLASS_NAME); $constraints = array( new ConstraintA(array('groups' => array( 'Default', - 'EntityInterface', + 'EntityInterfaceA', 'EntityParent', 'Entity', ))), @@ -52,6 +54,17 @@ public function testMergeParentConstraints() 'EntityParent', 'Entity', ))), + new ConstraintA(array('groups' => array( + 'Default', + 'EntityParentInterface', + 'EntityInterfaceB', + 'Entity', + ))), + new ConstraintA(array('groups' => array( + 'Default', + 'EntityInterfaceB', + 'Entity', + ))), new ConstraintA(array('groups' => array( 'Default', 'Entity', @@ -67,34 +80,36 @@ public function testWriteMetadataToCache() $factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache); $parentClassConstraints = array( - new ConstraintA(array('groups' => array('Default', 'EntityInterface', 'EntityParent'))), + new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA', 'EntityParent'))), new ConstraintA(array('groups' => array('Default', 'EntityParent'))), ); - $interfaceConstraints = array(new ConstraintA(array('groups' => array('Default', 'EntityInterface')))); + $interfaceAConstraints = array( + new ConstraintA(array('groups' => array('Default', 'EntityInterfaceA'))), + ); $cache->expects($this->never()) ->method('has'); $cache->expects($this->exactly(2)) ->method('read') ->withConsecutive( - array($this->equalTo(self::PARENTCLASS)), - array($this->equalTo(self::INTERFACECLASS)) + array($this->equalTo(self::PARENT_CLASS)), + array($this->equalTo(self::INTERFACE_A_CLASS)) ) ->will($this->returnValue(false)); $cache->expects($this->exactly(2)) ->method('write') ->withConsecutive( - $this->callback(function ($metadata) use ($interfaceConstraints) { - return $interfaceConstraints == $metadata->getConstraints(); + $this->callback(function ($metadata) use ($interfaceAConstraints) { + return $interfaceAConstraints == $metadata->getConstraints(); }), $this->callback(function ($metadata) use ($parentClassConstraints) { return $parentClassConstraints == $metadata->getConstraints(); }) ); - $metadata = $factory->getMetadataFor(self::PARENTCLASS); + $metadata = $factory->getMetadataFor(self::PARENT_CLASS); - $this->assertEquals(self::PARENTCLASS, $metadata->getClassName()); + $this->assertEquals(self::PARENT_CLASS, $metadata->getClassName()); $this->assertEquals($parentClassConstraints, $metadata->getConstraints()); } @@ -104,7 +119,7 @@ public function testReadMetadataFromCache() $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'); $factory = new LazyLoadingMetadataFactory($loader, $cache); - $metadata = new ClassMetadata(self::PARENTCLASS); + $metadata = new ClassMetadata(self::PARENT_CLASS); $metadata->addConstraint(new ConstraintA()); $loader->expects($this->never()) @@ -116,7 +131,7 @@ public function testReadMetadataFromCache() ->method('read') ->will($this->returnValue($metadata)); - $this->assertEquals($metadata, $factory->getMetadataFor(self::PARENTCLASS)); + $this->assertEquals($metadata, $factory->getMetadataFor(self::PARENT_CLASS)); } } diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 8e9d212191bc6..b7c7a8abbbf28 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -115,7 +115,7 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra )); if (isset($a[$prefix.'returnType'])) { - $a[$prefix.'returnType'] = (string) $a[$prefix.'returnType']; + $a[$prefix.'returnType'] = method_exists('ReflectionType', 'getName') ? $a[$prefix.'returnType']->getName() : $a[$prefix.'returnType']->__toString(); } if (isset($a[$prefix.'this'])) { $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); @@ -164,12 +164,13 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st 'position' => 'getPosition', 'isVariadic' => 'isVariadic', 'byReference' => 'isPassedByReference', + 'allowsNull' => 'allowsNull', )); try { if (method_exists($c, 'hasType')) { if ($c->hasType()) { - $a[$prefix.'typeHint'] = $c->getType()->__toString(); + $a[$prefix.'typeHint'] = method_exists('ReflectionType', 'getName') ? $c->getType()->getName() : $c->getType()->__toString(); } } else { $v = explode(' ', $c->__toString(), 6); @@ -182,15 +183,22 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st $a[$prefix.'typeHint'] = $m[1]; } } + if (!isset($a[$prefix.'typeHint'])) { + unset($a[$prefix.'allowsNull']); + } try { $a[$prefix.'default'] = $v = $c->getDefaultValue(); if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) { $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); } + if (null === $v) { + unset($a[$prefix.'allowsNull']); + } } catch (\ReflectionException $e) { - if (isset($a[$prefix.'typeHint']) && $c->allowsNull()) { + if (isset($a[$prefix.'typeHint']) && $c->allowsNull() && !method_exists('ReflectionType', 'getName')) { $a[$prefix.'default'] = null; + unset($a[$prefix.'allowsNull']); } } diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index 9a47aea7ee296..bd69f2eddf371 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -288,8 +288,7 @@ function isCtrlKey(e) { }; })(document); - -