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 daaa858dc78bc..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 = 'master' !== $version ? $version.'.999' : 'dev-master'; - $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') ?: '{"package":{"versions":[]}}'; - $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 428f19d92b334..d9bfbbbe0c6ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,24 +63,29 @@ before_install: - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = redis.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 - if [[ ! $skip ]]; then ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif; fi - if [[ ! $skip ]]; then ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif; 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-3.1.md b/CHANGELOG-3.1.md index 8b2959413df66..33ad4d31965d3 100644 --- a/CHANGELOG-3.1.md +++ b/CHANGELOG-3.1.md @@ -7,6 +7,51 @@ in 3.1 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/v3.1.0...v3.1.1 +* 3.1.5 (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 #20087 [VarDumper] Fix PHP 7.1 compat (nicolas-grekas) + * 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 #20051 Fix indexBy type extraction (lemoinem) + * bug #19951 [Finder] Trim trailing directory slash in ExcludeDirectoryFilterIterator (ro0NL) + * bug #19980 [Ldap] Fixed issue with legacy find() method not working as expected (csarrazi) + * bug #20026 [Cache] Fixed password used to make the redis connection. (ErikSaunier) + * bug #20018 [VarDumper] Fix test (nicolas-grekas) + * bug #20011 Use UUID for error codes for Form validator. (Koc) + * 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 #19784 [HttpKernel] Fixed the nullable support for php 7.1 and below (iltar) + * 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 #19853 [PropertyInfo] Make ReflectionExtractor compatible with ReflectionType changes in PHP 7.1 (teohhanhui) + * bug #19904 [Form] Fixed collapsed ChoiceType options attributes (HeahDude) + * bug #19872 [Filesystem] Consider the umask setting when dumping a file (leofeyer) + * bug #19908 [Config] Handle open_basedir restrictions in FileLocator (Nicofuma) + * bug #19893 [FrameworkBundle] Remove cache clearer default value in config (nicolas-grekas) + * bug #19924 [DoctrineBridge][PropertyInfo] Treat Doctrine decimal type as string (teohhanhui) + * bug #19932 Fixed bad merge (GrahamCampbell) + * 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) + * bug #19878 Fix translation:update command count (tgalopin) + * bug #19859 [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1) (nicolas-grekas) + * bug #19780 [FrameworkBundle] Incorrect line break in exception message (500 debug page) (pedroresende) + * bug #19595 [form] lazy trans `post_max_size_message`. (aitboudad) + * bug #19870 [DI] Fix setting synthetic services on ContainerBuilder (nicolas-grekas) + * bug #19848 Revert "minor #19689 [DI] Cleanup array_key_exists (ro0NL)" (nicolas-grekas) + * bug #19842 [FrameworkBundle] Check for class existence before is_subclass_of (chalasr) + * bug #19827 [BrowserKit] Fix cookie expiration on 32 bit systems (jameshalsall) + * 3.1.4 (2016-09-03) * bug #19812 [WebProfilerBundle] Fix margin on toolbar route panel when no route is found in the request (jameshalsall) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index da27714faff54..7cbed979c4960 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -52,21 +52,22 @@ Symfony is the result of the work of many people who made the code better - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Peter Rehm (rpet) - Ener-Getick (energetick) + - Peter Rehm (rpet) - Iltar van der Berg (kjarli) - Kevin Bond (kbond) + - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Matthias Pigulla (mpdude) - - Andrej Hudec (pulzarraider) - Christian Raue + - Arnout Boks (aboks) - Charles Sarrazin (csarrazi) + - Robin Chalas (chalas_r) - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Arnout Boks (aboks) - Douglas Greenshields (shieldo) - Lee McDermott - Brandon Turner @@ -80,14 +81,14 @@ Symfony is the result of the work of many people who made the code better - Toni Uebernickel (havvg) - Fran Moreno (franmomu) - Antoine Hérault (herzult) - - Robin Chalas (chalas_r) - Arnaud Le Blanc (arnaud-lb) - Jérôme Tamarelle (gromnan) - Paráda József (paradajozsef) + - Titouan Galopin (tgalopin) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - - Brice BERNARD (brikou) - Konstantin Myakshin (koc) + - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - Dariusz Ruminski - marc.weistroff @@ -114,15 +115,14 @@ Symfony is the result of the work of many people who made the code better - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - - Titouan Galopin (tgalopin) - Stefano Sala (stefano.sala) + - Evgeniy (ewgraf) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) - Sebastian Hörl (blogsh) - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Sebastiaan Stok (sstok) - - Evgeniy (ewgraf) - Tugdual Saunier (tucksaun) - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) @@ -132,6 +132,7 @@ Symfony is the result of the work of many people who made the code better - Arnaud Kleinpeter (nanocom) - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) + - Vyacheslav Pavlov - Richard Shank (iampersistent) - Thomas Rabaix (rande) - Vincent AUBERT (vincent) @@ -161,9 +162,9 @@ Symfony is the result of the work of many people who made the code better - Noel Guilbert (noel) - Stepan Anchugov (kix) - bronze1man + - Roland Franssen (ro0) - sun (sun) - Larry Garfield (crell) - - Vyacheslav Pavlov - Martin Schuhfuß (usefulthink) - Matthieu Bontemps (mbontemps) - Pierre Minnieur (pminnieur) @@ -179,12 +180,15 @@ Symfony is the result of the work of many people who made the code better - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Michele Orselli (orso) + - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Lars Strojny (lstrojny) - Rui Marinho (ruimarinho) - Daniel Espendiller + - Dawid Nowak - Eugene Wissner - Julien Brochet (mewt) + - Yonel Ceruto González (yonelceruto) - Sergey Linnik (linniksa) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) @@ -205,8 +209,8 @@ Symfony is the result of the work of many people who made the code better - Danny Berger (dpb587) - Jérôme Vasseur - Roman Marintšenko (inori) + - Christian Schmidt - Xavier Montaña Carreras (xmontana) - - Tom Van Looy (tvlooy) - Chris Wilkinson (thewilkybarkid) - Mickaël Andrieu (mickaelandrieu) - Xavier Perez @@ -214,8 +218,8 @@ Symfony is the result of the work of many people who made the code better - Katsuhiro OGAWA - Alif Rachmawadi - Kristen Gilden (kgilden) - - Dawid Nowak - Pierre-Yves LEBECQ (pylebecq) + - Alex Pott - Jakub Kucharovic (jkucharovic) - Eugene Leonovich (rybakit) - Filippo Tessarotto @@ -227,8 +231,10 @@ Symfony is the result of the work of many people who made the code better - Ray - Grégoire Paris (greg0ire) - Chekote + - Tobias Nyholm (tobias) - Thomas Adam - Albert Casademont (acasademont) + - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) - jdhoek - Nikita Konstantinov @@ -242,7 +248,6 @@ Symfony is the result of the work of many people who made the code better - Roumen Damianoff (roumen) - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) - - Christian Schmidt - Wouter Van Hecke - Peter Kruithof (pkruithof) - Michael Holm (hollo) @@ -257,17 +262,15 @@ Symfony is the result of the work of many people who made the code better - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) - Gabor Toth (tgabi333) - - Alex Pott - realmfoo - Thomas Tourlourat (armetiz) - Andrey Esaulov (andremaha) - - Tobias Nyholm (tobias) - Grégoire Passault (gregwar) + - Leo Feyer - Ismael Ambrosi (iambrosi) - Uwe Jäger (uwej711) - Aurelijus Valeiša (aurelijus) - Jan Decavele (jandc) - - Yonel Ceruto González (yonelceruto) - Gustavo Piltcher - Stepan Tanasiychuk (stfalcon) - Tiago Ribeiro (fixe) @@ -306,17 +309,20 @@ Symfony is the result of the work of many people who made the code better - Felix Labrecque - Yaroslav Kiliba - Terje Bråten - - Roland Franssen (ro0) - Robbert Klarenbeek (robbertkl) + - Marek Štípek (maryo) - Alessandro Chitolina - 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) @@ -328,7 +334,6 @@ Symfony is the result of the work of many people who made the code better - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer - - Jhonny Lidfors (jhonne) - Shein Alexey - Baptiste Lafontaine - Joe Lencioni @@ -383,7 +388,6 @@ Symfony is the result of the work of many people who made the code better - cedric lombardot (cedriclombardot) - Jonas Flodén (flojon) - Christian Schmidt - - Marek Štípek (maryo) - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - Marek Pietrzak @@ -409,7 +413,6 @@ Symfony is the result of the work of many people who made the code better - Benoît Burnichon (bburnichon) - Sebastian Bergmann - Pablo Díez (pablodip) - - SpacePossum - Kevin McBride - Philipp Rieber (bicpi) - Manuel de Ruiter (manuel) @@ -428,6 +431,7 @@ Symfony is the result of the work of many people who made the code better - Filip Procházka (fprochazka) - mmoreram - Markus Lanthaler (lanthaler) + - Remi Collet - Vicent Soria Durá (vicentgodella) - Nicolas Dewez (nicolas_dewez) - Anthony Ferrara @@ -435,7 +439,7 @@ Symfony is the result of the work of many people who made the code better - Jakub Škvára (jskvara) - Andrew Udvare (audvare) - alexpods - - Tristan Darricau (nicofuma) + - Michele Locati - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) - Almog Baku (almogbaku) @@ -449,13 +453,13 @@ Symfony is the result of the work of many people who made the code better - DUPUCH (bdupuch) - Benjamin Leveque (benji07) - Nate (frickenate) + - Timothée Barray (tyx) - jhonnyL - sasezaki - Dawid Pakuła (zulusx) - Florian Rey (nervo) - Oskar Stark (oskarstark) - Rodrigo Borrego Bernabé (rodrigobb) - - Leo Feyer - MatTheCat - Denis Gorbachev (starfall) - Peter van Dommelen @@ -557,6 +561,7 @@ Symfony is the result of the work of many people who made the code better - Hossein Bukhamsin - Disparity - origaminal + - Maxime STEINHAUSSER - Paweł Wacławczyk (pwc) - Oleg Zinchenko (cystbear) - Johannes Klauss (cloppy) @@ -567,6 +572,7 @@ Symfony is the result of the work of many people who made the code better - Tiago Brito (blackmx) - Richard van den Brand (ricbra) - develop + - ReenExe - Mark Sonnabaum - Richard Quadling - jochenvdv @@ -596,7 +602,6 @@ Symfony is the result of the work of many people who made the code better - Lars Vierbergen - Dennis Hotson - Andrew Tchircoff (andrewtch) - - Remi Collet - michaelwilliams - 1emming - Leevi Graham (leevigraham) @@ -619,7 +624,6 @@ Symfony is the result of the work of many people who made the code better - possum - Denis Zunke (donalberto) - Olivier Maisonneuve (olineuve) - - Michele Locati - Masterklavi - Francis Turmel (fturmel) - cgonzalez @@ -630,6 +634,7 @@ Symfony is the result of the work of many people who made the code better - Harm van Tilborg - Jan Prieser - Adrien Lucas (adrienlucas) + - Zhuravlev Alexander (scif) - James Michael DuPont - Tom Klingenberg - Christopher Hall (mythmakr) @@ -681,7 +686,6 @@ Symfony is the result of the work of many people who made the code better - abdul malik ikhsan (samsonasik) - Henry Snoek (snoek09) - Simone Di Maulo (toretto460) - - Timothée Barray (tyx) - Sander Toonen (xatoo) - Christian Morgan - Alexander Miehe (engerim) @@ -801,7 +805,6 @@ Symfony is the result of the work of many people who made the code better - Ken Marfilla (marfillaster) - benatespina (benatespina) - Denis Kop - - Maxime STEINHAUSSER - jfcixmedia - Martijn Evers - Benjamin Paap (benjaminpaap) @@ -834,6 +837,7 @@ 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 @@ -855,6 +859,7 @@ Symfony is the result of the work of many people who made the code better - Gustavo Adrian - Yannick - spdionis + - Taras Girnyk - Eduardo García Sanz (coma) - James Gilliland - Rhodri Pugh (rodnaph) @@ -882,6 +887,7 @@ 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 @@ -946,6 +952,7 @@ Symfony is the result of the work of many people who made the code better - ShiraNai7 - Vašek Purchart (vasek-purchart) - Janusz Jabłoński (yanoosh) + - Sandro Hopf - Łukasz Makuch - George Giannoulopoulos - Daniel Richter (richtermeister) @@ -971,7 +978,6 @@ Symfony is the result of the work of many people who made the code better - WedgeSama - Felds Liscia - Ahmed TAILOULOUTE (ahmedtai) - - James Halsall (jaitsu) - Maxime Veber (nek-) - Sullivan SENECHAL - Tadcka @@ -1026,6 +1032,7 @@ Symfony is the result of the work of many people who made the code better - Valentin VALCIU - Kevin Dew - James Cowgill + - 1ma (jautenim) - Nicolas Schwartz (nicoschwartz) - Patrik Gmitter (patie) - Jonathan Gough @@ -1102,8 +1109,8 @@ Symfony is the result of the work of many people who made the code better - David Stone - Jovan Perovic (jperovic) - Pablo Maria Martelletti (pmartelletti) - - Zhuravlev Alexander (scif) - Yassine Guedidi (yguedidi) + - Waqas Ahmed - Luis Muñoz - Andreas - Thomas Chmielowiec @@ -1185,6 +1192,7 @@ Symfony is the result of the work of many people who made the code better - Adam - devel - taiiiraaa + - Johann Pardanaud - Trevor Suarez - gedrox - dropfen @@ -1294,6 +1302,7 @@ Symfony is the result of the work of many people who made the code better - Muriel (metalmumu) - Michael Pohlers (mick_the_big) - Cayetano Soriano Gallego (neoshadybeat) + - Ondrej Machulda (ondram) - Patrick McDougle (patrick-mcdougle) - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) @@ -1313,6 +1322,7 @@ Symfony is the result of the work of many people who made the code better - Joseph Deray - Damian Sromek - Ben + - Evgeniy Tetenchuk - dasmfm - Arnaud Buathier (arnapou) - chesteroni (chesteroni) @@ -1403,6 +1413,7 @@ Symfony is the result of the work of many people who made the code better - Benjamin Long - Matt Janssen - Peter Gribanov + - Ben Johnson - kwiateusz - David Soria Parra - Sergiy Sokolenko @@ -1526,6 +1537,7 @@ Symfony is the result of the work of many people who made the code better - smokeybear87 - Gustavo Adrian - Kevin Weber + - Dionysis Arvanitis - Sergey Fedotov - Michael - fh-github@fholzhauer.de diff --git a/appveyor.yml b/appveyor.yml index d72c5b8fe7a8c..42b5a5113ac93 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,18 +44,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 f2f90c2950557..2c32fe2d087ac 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "doctrine/common": "~2.4", - "twig/twig": "~1.23|~2.0", + "twig/twig": "~1.26|~2.0", "psr/cache": "~1.0", "psr/log": "~1.0", "symfony/polyfill-intl-icu": "~1.0", @@ -85,6 +85,7 @@ "monolog/monolog": "~1.11", "ocramius/proxy-manager": "~0.4|~1.0|~2.0", "predis/predis": "~1.0", + "symfony/phpunit-bridge": "~3.2", "egulias/email-validator": "~1.2,>=1.2.1", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", @@ -114,11 +115,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/phpunit.xml.dist b/phpunit.xml.dist index a350a926d38d2..7652c58475569 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -15,6 +15,7 @@ + diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index a93b20eed5f40..a0f8b5c46ad06 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -336,7 +336,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcache.class').'%'; $memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcache_instance.class').'%'; $memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcache_host').'%'; - $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; + $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; $cacheDef = new Definition($memcacheClass); $memcacheInstance = new Definition($memcacheInstanceClass); $memcacheInstance->addMethodCall('connect', array( diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index 6e8c29e16b0dd..aba31792f99ee 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -88,7 +88,8 @@ public function getTypes($class, $property, array $context = array()) if (isset($associationMapping['indexBy'])) { $indexProperty = $associationMapping['indexBy']; - $typeOfField = $metadata->getTypeOfField($indexProperty); + $subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); $collectionKeyType = $this->getPhpType($typeOfField); } @@ -178,12 +179,12 @@ private function getPhpType($doctrineType) return Type::BUILTIN_TYPE_INT; case DBALType::FLOAT: - case DBALType::DECIMAL: return Type::BUILTIN_TYPE_FLOAT; case DBALType::STRING: case DBALType::TEXT: case DBALType::GUID: + case DBALType::DECIMAL: return Type::BUILTIN_TYPE_STRING; case DBALType::BOOLEAN: diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 1bc57b1140fae..2224517db6708 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -49,6 +49,8 @@ public function testGetProperties() 'time', 'json', 'simpleArray', + 'float', + 'decimal', 'bool', 'binary', 'customFoo', @@ -73,6 +75,8 @@ public function typesProvider() return array( array('id', array(new Type(Type::BUILTIN_TYPE_INT))), array('guid', array(new Type(Type::BUILTIN_TYPE_STRING))), + array('float', array(new Type(Type::BUILTIN_TYPE_FLOAT))), + array('decimal', array(new Type(Type::BUILTIN_TYPE_STRING))), array('bool', array(new Type(Type::BUILTIN_TYPE_BOOL))), array('binary', array(new Type(Type::BUILTIN_TYPE_RESOURCE))), array('json', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true))), diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 317d14257b203..ad3b7b9227652 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -41,7 +41,7 @@ class DoctrineDummy public $bar; /** - * @ManyToMany(targetEntity="DoctrineRelation", indexBy="guid") + * @ManyToMany(targetEntity="DoctrineRelation", indexBy="rguid") */ protected $indexedBar; @@ -65,6 +65,16 @@ class DoctrineDummy */ private $simpleArray; + /** + * @Column(type="float") + */ + private $float; + + /** + * @Column(type="decimal", precision=10, scale=2) + */ + private $decimal; + /** * @Column(type="boolean") */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php index 23f64d829e030..6e94e028faa7d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php @@ -31,5 +31,5 @@ class DoctrineRelation /** * @Column(type="guid") */ - protected $guid; + protected $rguid; } diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index cd3af44a81f16..8b6555cfe2556 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -107,7 +107,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/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 861de86909722..a18b817870f5e 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -139,7 +139,6 @@ private function getMetadata($type, $entity) return; } if ($type === 'functions' || $type === 'filters') { - $args = array(); $cb = $entity->getCallable(); if (is_null($cb)) { return; diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 545ddcebe2aee..1f43afcdc44f0 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -105,7 +105,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $template .= fread(STDIN, 1024); } - return $this->display($input, $output, $io, array($this->validate($twig, $template, uniqid('sf_')))); + return $this->display($input, $output, $io, 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, JSON_PRETTY_PRINT)); + $output->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); 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 3d62ce68809ba..52d79eb6129f8 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 2aea02ad4051c..599f2c8c34b00 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 1dc7056e15a4a..9798e6ddf4b0c 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 4b9a6bd4e79d8..51939d0eed1ce 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.5.9", - "twig/twig": "~1.23|~2.0" + "twig/twig": "~1.26|~2.0" }, "require-dev": { "symfony/asset": "~2.8|~3.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index a9a004735b11f..72298480b4e31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -160,11 +160,8 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($operation->getDomains() as $domain) { $newKeys = array_keys($operation->getNewMessages($domain)); $allKeys = array_keys($operation->getMessages($domain)); - $domainMessagesCount = count($newKeys) + count($allKeys); - $io->section(sprintf('Messages extracted for domain "%s" (%d messages)', $domain, $domainMessagesCount)); - - $io->listing(array_merge( + $list = array_merge( array_diff($allKeys, $newKeys), array_map(function ($id) { return sprintf('%s', $id); @@ -172,7 +169,12 @@ protected function execute(InputInterface $input, OutputInterface $output) array_map(function ($id) { return sprintf('%s', $id); }, array_keys($operation->getObsoleteMessages($domain))) - )); + ); + + $domainMessagesCount = count($list); + + $io->section(sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); + $io->listing($list); $extractedMessagesCount += $domainMessagesCount; } @@ -181,7 +183,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->comment('Xliff output version is 1.2'); } - $resultMessage = sprintf('%d messages were successfully extracted', $extractedMessagesCount); + $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); } if ($input->getOption('no-backup') === true) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index eb3508449b593..19195674c0300 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -82,7 +82,6 @@ protected function execute(InputInterface $input, OutputInterface $output) throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); } - $files = array(); if (is_file($filename)) { $files = array($filename); } elseif (is_dir($filename)) { @@ -158,7 +157,7 @@ private function displayJson(OutputInterface $output, $filesInfo) } }); - $output->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT)); + $output->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); return min($errors, 1); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php index 6c20c83af106f..b5211755065df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php @@ -35,6 +35,10 @@ public function process(ContainerBuilder $container) $class = $container->getParameterBag()->resolveValue($definition->getClass()); if (!is_subclass_of($class, 'Symfony\\Component\\Console\\Command\\Command')) { + if (!class_exists($class, false)) { + throw new \InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "Symfony\\Component\\Console\\Command\\Command".', $id)); } $container->setAlias($serviceId = 'console.command.'.strtolower(str_replace('\\', '_', $class)), $id); 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/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 4c153f0629c4a..eb7c2d85ba633 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -585,7 +585,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->scalarNode('provider') ->info('The service name to use as provider when the specified adapter needs one.') ->end() - ->scalarNode('clearer')->defaultValue('cache.default_clearer')->end() + ->scalarNode('clearer')->end() ->end() ->end() ->validate() diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 7ed44c5bb84d2..dd0e839bf93e2 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/public/css/body.css b/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css index c50c1a54c7868..9a1cbb8cc2755 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css @@ -39,7 +39,7 @@ build: 56 font-family: Georgia, "Times New Roman", Times, serif; font-size: 20px; color: #313131; - word-break: break-all; + word-wrap: break-word; } .sf-reset li { padding-bottom: 10px; 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/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index f7eca9d366d38..40eab748c62bf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -28,6 +28,15 @@ public function testDumpMessagesAndClean() $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true)); $this->assertRegExp('/foo/', $tester->getDisplay()); + $this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay()); + } + + public function testDumpTwoMessagesAndClean() + { + $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo', 'bar' => 'bar'))); + $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true)); + $this->assertRegExp('/foo/', $tester->getDisplay()); + $this->assertRegExp('/bar/', $tester->getDisplay()); $this->assertRegExp('/2 messages were successfully extracted/', $tester->getDisplay()); } 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/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php index 565354343e2d7..2318c2da6244c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php @@ -17,6 +17,16 @@ class CachePoolsTest extends WebTestCase { + protected function setUp() + { + $_SERVER['SYMFONY__REDIS_HOST'] = getenv('REDIS_HOST'); + } + + protected function tearDown() + { + unset($_SERVER['SYMFONY__REDIS_HOST']); + } + public function testCachePools() { $this->doTestCachePools(array(), FilesystemAdapter::class); @@ -30,7 +40,7 @@ public function testRedisCachePools() try { $this->doTestCachePools(array('root_config' => 'redis_config.yml', 'environment' => 'redis_cache'), RedisAdapter::class); } catch (\PHPUnit_Framework_Error_Warning $e) { - if (0 !== strpos($e->getMessage(), 'unable to connect to 127.0.0.1')) { + if (0 !== strpos($e->getMessage(), 'unable to connect to')) { throw $e; } $this->markTestSkipped($e->getMessage()); @@ -50,7 +60,7 @@ public function testRedisCustomCachePools() try { $this->doTestCachePools(array('root_config' => 'redis_custom_config.yml', 'environment' => 'custom_redis_cache'), RedisAdapter::class); } catch (\PHPUnit_Framework_Error_Warning $e) { - if (0 !== strpos($e->getMessage(), 'unable to connect to 127.0.0.1')) { + if (0 !== strpos($e->getMessage(), 'unable to connect to')) { throw $e; } $this->markTestSkipped($e->getMessage()); @@ -62,22 +72,28 @@ public function doTestCachePools($options, $adapterClass) static::bootKernel($options); $container = static::$kernel->getContainer(); - $pool = $container->get('cache.test'); - $this->assertInstanceOf($adapterClass, $pool); + $pool1 = $container->get('cache.pool1'); + $this->assertInstanceOf($adapterClass, $pool1); $key = 'foobar'; - $pool->deleteItem($key); - $item = $pool->getItem($key); + $pool1->deleteItem($key); + $item = $pool1->getItem($key); $this->assertFalse($item->isHit()); $item->set('baz'); - $pool->save($item); - $item = $pool->getItem($key); + $pool1->save($item); + $item = $pool1->getItem($key); $this->assertTrue($item->isHit()); + $pool2 = $container->get('cache.pool2'); + $pool2->save($item); + $container->get('cache_clearer')->clear($container->getParameter('kernel.cache_dir')); - $item = $pool->getItem($key); + $item = $pool1->getItem($key); $this->assertFalse($item->isHit()); + + $item = $pool2->getItem($key); + $this->assertTrue($item->isHit()); } protected static function createKernel(array $options = array()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml index 20d966780c918..eabf83825e05d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml @@ -4,5 +4,10 @@ imports: framework: cache: pools: - cache.test: + cache.pool1: public: true + cache.pool2: + public: true + adapter: cache.pool3 + cache.pool3: + clearer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml index ae1fbf62a6ff3..2794a72c809d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml @@ -4,6 +4,10 @@ imports: framework: cache: app: cache.adapter.redis + default_redis_provider: "redis://%redis_host%" pools: - cache.test: + cache.pool1: public: true + cache.pool2: + public: true + clearer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml index 3c99f05ac75cc..70a51b272e5a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml @@ -6,7 +6,7 @@ services: public: false class: Redis calls: - - [connect, [127.0.0.1]] + - [connect, ['%redis_host%']] cache.app: parent: cache.adapter.redis @@ -17,5 +17,8 @@ services: framework: cache: pools: - cache.test: + cache.pool1: public: true + cache.pool2: + public: true + clearer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist index 1d25eeb3304c5..a105f7ece0a98 100644 --- a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist @@ -8,6 +8,7 @@ > + diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index a67980b64313c..64a1ad32e650c 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -22,6 +22,7 @@ "symfony/polyfill-php70": "~1.0" }, "require-dev": { + "symfony/asset": "~2.8|~3.0", "symfony/browser-kit": "~2.8|~3.0", "symfony/console": "~2.8|~3.0", "symfony/css-selector": "~2.8|~3.0", @@ -30,6 +31,7 @@ "symfony/framework-bundle": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", "symfony/security-acl": "~2.8|~3.0", + "symfony/templating": "~2.8|~3.0", "symfony/twig-bundle": "~2.8|~3.0", "symfony/twig-bridge": "~2.8|~3.0", "symfony/process": "~2.8|~3.0", @@ -37,7 +39,7 @@ "symfony/yaml": "~2.8|~3.0", "symfony/expression-language": "~2.8|~3.0", "doctrine/doctrine-bundle": "~1.4", - "twig/twig": "~1.23|~2.0" + "twig/twig": "~1.26|~2.0" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" 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/Tests/Functional/CacheWarmingTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php index 610bfa3b58be1..56fd7f4245949 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php @@ -31,7 +31,7 @@ public function testCacheIsProperlyWarmedWhenTemplatingIsAvailable() $this->assertTrue(file_exists($kernel->getCacheDir().'/twig')); } - public function testCacheIsNotWarmedWhenTemplatingIsDisabled() + public function testCacheIsProperlyWarmedWhenTemplatingIsDisabled() { $kernel = new CacheWarmingKernel(false); $kernel->boot(); @@ -40,7 +40,7 @@ public function testCacheIsNotWarmedWhenTemplatingIsDisabled() $warmer->enableOptionalWarmers(); $warmer->warmUp($kernel->getCacheDir()); - $this->assertFalse(file_exists($kernel->getCacheDir().'/twig')); + $this->assertTrue(file_exists($kernel->getCacheDir().'/twig')); } protected function setUp() @@ -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/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 5f7ca97889efc..2e2b74a06f4e2 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -20,7 +20,8 @@ "symfony/asset": "~2.8|~3.0", "symfony/twig-bridge": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0" + "symfony/http-kernel": "~2.8|~3.0", + "twig/twig": "~1.26|~2.0" }, "require-dev": { "symfony/stopwatch": "~2.8|~3.0", @@ -31,7 +32,8 @@ "symfony/routing": "~2.8|~3.0", "symfony/templating": "~2.8|~3.0", "symfony/yaml": "~2.8|~3.0", - "symfony/framework-bundle": "~2.8|~3.0" + "symfony/framework-bundle": "~2.8|~3.0", + "doctrine/annotations": "~1.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php index ab67078dd6ecd..2dc0b618d5302 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php +++ b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php @@ -108,8 +108,6 @@ public function onKernelResponse(FilterResponseEvent $event) /** * Injects the web debug toolbar into the given Response. - * - * @param Response $response A Response instance */ protected function injectToolbar(Response $response, Request $request) { 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/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index 604d12d84d55a..eeef805d72099 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -76,7 +76,7 @@ public function __construct($name, $value, $expires = null, $path = null, $domai throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.', $expires)); } - $this->expires = $timestampAsDateTime->getTimestamp(); + $this->expires = $timestampAsDateTime->format('U'); } } @@ -205,13 +205,13 @@ private static function parseDate($dateValue) foreach (self::$dateFormats as $dateFormat) { if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) { - return $date->getTimestamp(); + return $date->format('U'); } } // attempt a fallback for unusual formatting if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) { - return $date->getTimestamp(); + return $date->format('U'); } throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue)); @@ -304,6 +304,6 @@ public function isHttpOnly() */ public function isExpired() { - return null !== $this->expires && 0 !== $this->expires && $this->expires < time(); + return null !== $this->expires && 0 != $this->expires && $this->expires < time(); } } diff --git a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php index 61b364e6d1eac..5a724333d350f 100644 --- a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php @@ -178,7 +178,7 @@ public function testIsExpired() } /** - * @expectedException UnexpectedValueException + * @expectedException \UnexpectedValueException * @expectedExceptionMessage The cookie expiration time "string" is not valid. */ public function testConstructException() diff --git a/src/Symfony/Component/Cache/Adapter/RedisAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisAdapter.php index 46c680afcc0c4..a636124acba9f 100644 --- a/src/Symfony/Component/Cache/Adapter/RedisAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/RedisAdapter.php @@ -69,7 +69,7 @@ public static function createConnection($dsn, array $options = array()) if (0 !== strpos($dsn, 'redis://')) { throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis://"', $dsn)); } - $params = preg_replace_callback('#^redis://(?:([^@]*)@)?#', function ($m) use (&$auth) { + $params = preg_replace_callback('#^redis://(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { if (isset($m[1])) { $auth = $m[1]; } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php index ff0b7eab2be18..86b16d436f23f 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php @@ -33,7 +33,7 @@ public static function setupBeforeClass() if (!extension_loaded('redis')) { self::markTestSkipped('Extension redis required.'); } - if (!@((new \Redis())->connect('127.0.0.1'))) { + if (!@((new \Redis())->connect(getenv('REDIS_HOST')))) { $e = error_get_last(); self::markTestSkipped($e['message']); } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterTest.php index 87a6db0736e0a..b2c87b23bbc4e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterTest.php @@ -19,12 +19,14 @@ class PredisAdapterTest extends AbstractRedisAdapterTest public static function setupBeforeClass() { parent::setupBeforeClass(); - self::$redis = new \Predis\Client(); + self::$redis = new \Predis\Client(array('host' => getenv('REDIS_HOST'))); } public function testCreateConnection() { - $redis = RedisAdapter::createConnection('redis://localhost/1', array('class' => \Predis\Client::class, 'timeout' => 3)); + $redisHost = getenv('REDIS_HOST'); + + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/1', array('class' => \Predis\Client::class, 'timeout' => 3)); $this->assertInstanceOf(\Predis\Client::class, $redis); $connection = $redis->getConnection(); @@ -32,7 +34,7 @@ public function testCreateConnection() $params = array( 'scheme' => 'tcp', - 'host' => 'localhost', + 'host' => $redisHost, 'path' => '', 'dbindex' => '1', 'port' => 6379, diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php index bef6862631ec1..c0174dd248222 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php @@ -32,7 +32,7 @@ public function createCachePool($defaultLifetime = 0) } /** - * @expectedException Exception + * @expectedException \Exception * @expectedExceptionMessage OK bar */ public function testProxyfiedItem() diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php index 2716f7b5abc6f..301d531ac3530 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php @@ -19,32 +19,34 @@ public static function setupBeforeClass() { parent::setupBeforeClass(); self::$redis = new \Redis(); - self::$redis->connect('127.0.0.1'); + self::$redis->connect(getenv('REDIS_HOST')); } public function testCreateConnection() { - $redis = RedisAdapter::createConnection('redis://localhost'); + $redisHost = getenv('REDIS_HOST'); + + $redis = RedisAdapter::createConnection('redis://'.$redisHost); $this->assertInstanceOf(\Redis::class, $redis); $this->assertTrue($redis->isConnected()); $this->assertSame(0, $redis->getDbNum()); - $redis = RedisAdapter::createConnection('redis://localhost/2'); + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/2'); $this->assertSame(2, $redis->getDbNum()); - $redis = RedisAdapter::createConnection('redis://localhost', array('timeout' => 3)); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, array('timeout' => 3)); $this->assertEquals(3, $redis->getTimeout()); - $redis = RedisAdapter::createConnection('redis://localhost?timeout=4'); + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'?timeout=4'); $this->assertEquals(4, $redis->getTimeout()); - $redis = RedisAdapter::createConnection('redis://localhost', array('read_timeout' => 5)); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, array('read_timeout' => 5)); $this->assertEquals(5, $redis->getReadTimeout()); } /** * @dataProvider provideFailedCreateConnection - * @expectedException Symfony\Component\Cache\Exception\InvalidArgumentException + * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Redis connection failed */ public function testFailedCreateConnection($dsn) @@ -63,7 +65,7 @@ public function provideFailedCreateConnection() /** * @dataProvider provideInvalidCreateConnection - * @expectedException Symfony\Component\Cache\Exception\InvalidArgumentException + * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Invalid Redis DSN */ public function testInvalidCreateConnection($dsn) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisArrayAdapterTest.php index d2968aea47c2c..bef3eb88729f5 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisArrayAdapterTest.php @@ -19,6 +19,6 @@ public static function setupBeforeClass() if (!class_exists('RedisArray')) { self::markTestSkipped('The RedisArray class is required.'); } - self::$redis = new \RedisArray(array('localhost'), array('lazy_connect' => true)); + self::$redis = new \RedisArray(array(getenv('REDIS_HOST')), array('lazy_connect' => true)); } } diff --git a/src/Symfony/Component/Cache/Tests/CacheItemTest.php b/src/Symfony/Component/Cache/Tests/CacheItemTest.php index 7b20a41ba2fe0..b9df6cb34939e 100644 --- a/src/Symfony/Component/Cache/Tests/CacheItemTest.php +++ b/src/Symfony/Component/Cache/Tests/CacheItemTest.php @@ -22,7 +22,7 @@ public function testValidKey() /** * @dataProvider provideInvalidKey - * @expectedException Symfony\Component\Cache\Exception\InvalidArgumentException + * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Cache key */ public function testInvalidKey($key) diff --git a/src/Symfony/Component/Cache/phpunit.xml.dist b/src/Symfony/Component/Cache/phpunit.xml.dist index 480bb6aeef0e0..3e164e64b50d9 100644 --- a/src/Symfony/Component/Cache/phpunit.xml.dist +++ b/src/Symfony/Component/Cache/phpunit.xml.dist @@ -8,6 +8,7 @@ > + diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php index 3ec68c6b5eecc..f94c82caa3149 100644 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -55,7 +55,12 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = $classes = array_unique($classes); - $cache = $cacheDir.'/'.$name.$extension; + // cache the core classes + if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { + throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir)); + } + $cacheDir = rtrim(realpath($cacheDir), '/'.DIRECTORY_SEPARATOR); + $cache = $cacheDir.DIRECTORY_SEPARATOR.$name.$extension; // auto-reload $reload = false; @@ -93,6 +98,10 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = $declared = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); } + $c = '(?:\s*+(?:(?:#|//)[^\n]*+\n|/\*(?:(?getFileName(); + $files[] = $file = $class->getFileName(); + $c = file_get_contents($file); - $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName())); + if (preg_match($strictTypesRegex, $c)) { + $file = explode(DIRECTORY_SEPARATOR, $file); - // fakes namespace declaration for global code - if (!$class->inNamespace()) { - $c = "\nnamespace\n{\n".$c."\n}\n"; - } + for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) { + if ($file[$i] !== $cacheDir[$i]) { + break; + } + } + if (1 >= $i) { + $file = var_export(implode(DIRECTORY_SEPARATOR, $file), true); + } else { + $file = array_slice($file, $i); + $file = str_repeat('..'.DIRECTORY_SEPARATOR, count($cacheDir) - $i).implode(DIRECTORY_SEPARATOR, $file); + $file = '__DIR__.'.var_export(DIRECTORY_SEPARATOR.$file, true); + } - $c = self::fixNamespaceDeclarations('\s*$/'), '', $c); - $content .= $c; - } + // fakes namespace declaration for global code + if (!$class->inNamespace()) { + $c = "\nnamespace\n{\n".$c."\n}\n"; + } - // cache the core classes - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { - throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir)); + $c = self::fixNamespaceDeclarations(' realpath(__DIR__).'/Fixtures/Namespaced/Foo.php', 'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php', 'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php', + 'Namespaced\WithStrictTypes' => realpath(__DIR__).'/Fixtures/Namespaced/WithStrictTypes.php', ), ), array(__DIR__.'/Fixtures/beta/NamespaceCollision', array( diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithStrictTypes.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithStrictTypes.php new file mode 100644 index 0000000000000..3c7870592b3cb --- /dev/null +++ b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithStrictTypes.php @@ -0,0 +1,13 @@ +cannotBeEmpty() is not applicable to BooleanNodeDefinition. */ public function testCannotBeEmptyThrowsAnException() diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php index 8f0cdbb4ebb5d..203413dbcc125 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php @@ -92,7 +92,7 @@ public function testFloatValidMinMaxAssertion() } /** - * @expectedException Symfony\Component\Config\Definition\Exception\InvalidDefinitionException + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException * @expectedExceptionMessage ->cannotBeEmpty() is not applicable to NumericNodeDefinition. */ public function testCannotBeEmptyThrowsAnException() diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 6434ef715284a..38f38e20232a9 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -35,6 +35,7 @@ use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -353,7 +354,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) @@ -781,6 +782,7 @@ protected function configureIO(InputInterface $input, OutputInterface $output) if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $input->setInteractive(false); } else { if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || $input->getParameterOption('--verbose', false, true) === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); @@ -831,17 +833,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/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index d212a3254752a..0d5001bb187a3 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -572,6 +572,8 @@ public function getSynopsis($short = false) * Add a command usage example. * * @param string $usage The usage, it'll be prefixed with the command name + * + * @return Command The current instance */ public function addUsage($usage) { diff --git a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php index d3d76a4201025..2eb9944d6213c 100644 --- a/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php @@ -98,7 +98,7 @@ protected function describeCommand(Command $command, array $options = array()) .'* Description: '.($command->getDescription() ?: '')."\n" .'* Usage:'."\n\n" .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) { - return $carry .= ' * `'.$usage.'`'."\n"; + return $carry.' * `'.$usage.'`'."\n"; }) ); diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index c6f5a409c3dc8..4012b088f2d41 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -198,6 +198,7 @@ protected function writeError(OutputInterface $output, \Exception $error) * * @param OutputInterface $output * @param Question $question + * @param resource $inputStream * * @return string */ @@ -314,7 +315,8 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu /** * Gets a hidden response from user. * - * @param OutputInterface $output An Output instance + * @param OutputInterface $output An Output instance + * @param resource $inputStream The handler resource * * @return string The answer * diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index cb0a8aa5f5004..f626c33e591bf 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -147,7 +147,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); } @@ -234,7 +237,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 974056d19913e..dcc4b0498fa0d 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -176,7 +176,7 @@ public function testSilentHelp() } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage The command "foofoo" does not exist. */ public function testGetInvalidCommand() @@ -212,7 +212,7 @@ public function testFindNamespaceWithSubnamespaces() } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage The namespace "f" is ambiguous (foo, foo1). */ public function testFindAmbiguousNamespace() @@ -225,7 +225,7 @@ public function testFindAmbiguousNamespace() } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage There are no commands defined in the "bar" namespace. */ public function testFindInvalidNamespace() @@ -235,7 +235,7 @@ public function testFindInvalidNamespace() } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Command "foo1" is not defined */ public function testFindUniqueNameButNamespaceName() @@ -313,7 +313,7 @@ public function testFindCommandWithMissingNamespace() /** * @dataProvider provideInvalidCommandNamesSingle - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Did you mean this */ public function testFindAlternativeExceptionMessageSingle($name) @@ -463,7 +463,7 @@ public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Command "foo::bar" is not defined. */ public function testFindWithDoubleColonInNameThrowsException() @@ -639,9 +639,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'); @@ -950,6 +952,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/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 53a6009e6c1eb..3bab819f40188 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -257,7 +257,7 @@ public function testExecuteMethodNeedsToBeOverridden() } /** - * @expectedException Symfony\Component\Console\Exception\InvalidOptionException + * @expectedException \Symfony\Component\Console\Exception\InvalidOptionException * @expectedExceptionMessage The "--bar" option does not exist. */ public function testRunWithInvalidOption() diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json index b3ad97d039c4e..dab170a354e25 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_1.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_1.json @@ -1 +1,154 @@ -{"commands":[{"name":"help","usage":["help [--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":{"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 [--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":{"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 [--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": { + "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 [--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": { + "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 e8870ba35dc7a..398f1fd0d0872 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json @@ -1 +1,336 @@ -{"commands":[{"name":"help","usage":["help [--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":{"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 [--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":{"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 [--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": { + "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 [--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": { + "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/application_astext1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_astext1.txt deleted file mode 100644 index 19dacb23bf7bc..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_astext1.txt +++ /dev/null @@ -1,20 +0,0 @@ -Console Tool - -Usage: - command [options] [arguments] - -Options: - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -Available commands: - afoobar The foo:bar command - help Displays help for a command - list Lists commands - foo - foo:bar The foo:bar command diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_astext2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_astext2.txt deleted file mode 100644 index c99ccdda7a6c6..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_astext2.txt +++ /dev/null @@ -1,16 +0,0 @@ -Console Tool - -Usage: - command [options] [arguments] - -Options: - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -Available commands for the "foo" namespace: - foo:bar The foo:bar command 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/command_astext.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_astext.txt deleted file mode 100644 index 4d9055d30918b..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_astext.txt +++ /dev/null @@ -1,18 +0,0 @@ -Usage: - namespace:name - name - -Arguments: - command The command to execute - -Options: - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -Help: - help diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_asxml.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_asxml.txt deleted file mode 100644 index 5e776238aa0a1..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_asxml.txt +++ /dev/null @@ -1,38 +0,0 @@ - - - - namespace:name - name - - description - help - - - The command to execute - - - - - - - - - - - - - diff --git a/src/Symfony/Component/Console/Tests/Fixtures/definition_astext.txt b/src/Symfony/Component/Console/Tests/Fixtures/definition_astext.txt deleted file mode 100644 index 0431c072ab220..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/definition_astext.txt +++ /dev/null @@ -1,11 +0,0 @@ -Arguments: - foo The foo argument - baz The baz argument [default: true] - bar The bar argument [default: ["http://foo.com/"]] - -Options: - -f, --foo=FOO The foo option - --baz[=BAZ] The baz option [default: false] - -b, --bar[=BAR] The bar option [default: "bar"] - --qux[=QUX] The qux option [default: ["http://foo.com/","bar"]] (multiple values allowed) - --qux2[=QUX2] The qux2 option [default: {"foo":"bar"}] (multiple values allowed) \ No newline at end of file diff --git a/src/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt b/src/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt deleted file mode 100644 index eec8c079ee3ee..0000000000000 --- a/src/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt +++ /dev/null @@ -1,39 +0,0 @@ - - - - - The foo argument - - - - The baz argument - - true - - - - The bar argument - - bar - - - - - - - - - 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/Helper/HelperSetTest.php b/src/Symfony/Component/Console/Tests/Helper/HelperSetTest.php index 04edd30411f59..998249dbc18af 100644 --- a/src/Symfony/Component/Console/Tests/Helper/HelperSetTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/HelperSetTest.php @@ -108,13 +108,6 @@ public function testIteration() } } - /** - * Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific - * helperset instance. - * - * @param string $name - * @param HelperSet $helperset allows a mock to verify a particular helperset set is being added to the Helper - */ private function getGenericMockHelper($name, HelperSet $helperset = null) { $mock_helper = $this->getMock('\Symfony\Component\Console\Helper\HelperInterface'); diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index a05a6b2c738cb..9eb34543772a8 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -695,7 +695,7 @@ public function testColumnWiths() } /** - * @expectedException Symfony\Component\Console\Exception\InvalidArgumentException + * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException * @expectedExceptionMessage Style "absent" is not defined. */ public function testIsNotDefinedStyleException() diff --git a/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php index 0a568a7b9bbc2..ecbe41df5934d 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')), @@ -343,4 +355,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 a013837dd6eb8..ed02e96cf41ef 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": ">=5.5.9", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/debug": "~2.8|~3.0" }, "require-dev": { "symfony/event-dispatcher": "~2.8|~3.0", diff --git a/src/Symfony/Component/CssSelector/XPath/Translator.php b/src/Symfony/Component/CssSelector/XPath/Translator.php index 8cbea5ca9568e..2cc2b110c93c3 100644 --- a/src/Symfony/Component/CssSelector/XPath/Translator.php +++ b/src/Symfony/Component/CssSelector/XPath/Translator.php @@ -70,9 +70,6 @@ class Translator implements TranslatorInterface */ private $attributeMatchingTranslators = array(); - /** - * Constructor. - */ public function __construct(ParserInterface $parser = null) { $this->mainParser = $parser ?: new Parser(); diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 04fba93ac8f7e..b089737cbc359 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -348,10 +348,12 @@ private function reRegister($prev) /** * Handles errors by filtering then logging them according to the configured bit fields. * - * @param int $type One of the E_* constants + * @param int $type One of the E_* constants + * @param string $message * @param string $file * @param int $line * @param array $context + * @param array $backtrace * * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself * diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php index 508a8978ea68b..59d4e0a767a5a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php @@ -56,14 +56,12 @@ public function __construct(array $passes) */ public function process(ContainerBuilder $container) { - $this->repeat = false; - foreach ($this->passes as $pass) { - $pass->process($container); - } - - if ($this->repeat) { - $this->process($container); - } + do { + $this->repeat = false; + foreach ($this->passes as $pass) { + $pass->process($container); + } + } while ($this->repeat); } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php index 056be7fa3f5d4..e3c793c4f4eaf 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php @@ -39,7 +39,7 @@ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceRefere /** * Returns the value of the edge. * - * @return ServiceReferenceGraphNode + * @return string */ public function getValue() { diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d791ebc2a65cd..f5b9091a219f6 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -341,7 +341,8 @@ public function set($id, $service) { $id = strtolower($id); - if ($this->isFrozen() && (!isset($this->definitions[$id]) || !$this->definitions[$id]->isSynthetic())) { + if ($this->isFrozen() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) { + // setting a synthetic service on a frozen container is alright throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a frozen container is not allowed.', $id)); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php index 376487d3ab9f3..42f14b7b7a82d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php @@ -128,7 +128,7 @@ private function addEdges() * * @return array An array of edges */ - private function findEdges($id, $arguments, $required, $name) + private function findEdges($id, array $arguments, $required, $name) { $edges = array(); foreach ($arguments as $argument) { @@ -241,7 +241,7 @@ private function endDot() * * @return string A comma separated list of attributes */ - private function addAttributes($attributes) + private function addAttributes(array $attributes) { $code = array(); foreach ($attributes as $k => $v) { @@ -258,7 +258,7 @@ private function addAttributes($attributes) * * @return string A space separated list of options */ - private function addOptions($options) + private function addOptions(array $options) { $code = array(); foreach ($options as $k => $v) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 78a8a14b560f5..66afcb882250a 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -374,7 +374,7 @@ private function addServiceReturn($id, $definition) * @throws InvalidArgumentException * @throws RuntimeException */ - private function addServiceInstance($id, $definition) + private function addServiceInstance($id, Definition $definition) { $class = $definition->getClass(); @@ -422,7 +422,7 @@ private function addServiceInstance($id, $definition) * * @return bool */ - private function isSimpleInstance($id, $definition) + private function isSimpleInstance($id, Definition $definition) { foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) { if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) { @@ -446,7 +446,7 @@ private function isSimpleInstance($id, $definition) * * @return string */ - private function addServiceMethodCalls($id, $definition, $variableName = 'instance') + private function addServiceMethodCalls($id, Definition $definition, $variableName = 'instance') { $calls = ''; foreach ($definition->getMethodCalls() as $call) { @@ -461,7 +461,7 @@ private function addServiceMethodCalls($id, $definition, $variableName = 'instan return $calls; } - private function addServiceProperties($id, $definition, $variableName = 'instance') + private function addServiceProperties($id, Definition $definition, $variableName = 'instance') { $code = ''; foreach ($definition->getProperties() as $name => $value) { @@ -481,7 +481,7 @@ private function addServiceProperties($id, $definition, $variableName = 'instanc * * @throws ServiceCircularReferenceException when the container contains a circular reference */ - private function addServiceInlinedDefinitionsSetup($id, $definition) + private function addServiceInlinedDefinitionsSetup($id, Definition $definition) { $this->referenceVariables[$id] = new Variable('instance'); @@ -525,7 +525,7 @@ private function addServiceInlinedDefinitionsSetup($id, $definition) * * @return string */ - private function addServiceConfigurator($id, $definition, $variableName = 'instance') + private function addServiceConfigurator($id, Definition $definition, $variableName = 'instance') { if (!$callable = $definition->getConfigurator()) { return ''; @@ -561,7 +561,7 @@ private function addServiceConfigurator($id, $definition, $variableName = 'insta * * @return string */ - private function addService($id, $definition) + private function addService($id, Definition $definition) { $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); @@ -1032,7 +1032,7 @@ protected function getDefaultParameters() * * @throws InvalidArgumentException */ - private function exportParameters($parameters, $path = '', $indent = 12) + private function exportParameters(array $parameters, $path = '', $indent = 12) { $php = array(); foreach ($parameters as $key => $value) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 68ce5005d07aa..bd51e82d83a4a 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -271,7 +271,7 @@ private function addServices(\DOMElement $parent) * @param \DOMElement $parent * @param string $keyAttribute */ - private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key') + private function convertParameters(array $parameters, $type, \DOMElement $parent, $keyAttribute = 'key') { $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1); foreach ($parameters as $key => $value) { @@ -317,7 +317,7 @@ private function convertParameters($parameters, $type, \DOMElement $parent, $key * * @return array */ - private function escape($arguments) + private function escape(array $arguments) { $args = array(); foreach ($arguments as $k => $v) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 24ec562a403c7..1a3efdd3953d2 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -307,7 +307,7 @@ private function getExpressionCall($expression) * * @return array */ - private function prepareParameters($parameters, $escape = true) + private function prepareParameters(array $parameters, $escape = true) { $filtered = array(); foreach ($parameters as $key => $value) { @@ -330,7 +330,7 @@ private function prepareParameters($parameters, $escape = true) * * @return array */ - private function escape($arguments) + private function escape(array $arguments) { $args = array(); foreach ($arguments as $k => $v) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index f92925eac5563..82bbf901828d4 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -425,9 +425,9 @@ private function resolveServices($value) { if (is_array($value)) { $value = array_map(array($this, 'resolveServices'), $value); - } elseif (is_string($value) && 0 === strpos($value, '@=')) { + } elseif (is_string($value) && 0 === strpos($value, '@=')) { return new Expression(substr($value, 2)); - } elseif (is_string($value) && 0 === strpos($value, '@')) { + } elseif (is_string($value) && 0 === strpos($value, '@')) { if (0 === strpos($value, '@@')) { $value = substr($value, 1); $invalidBehavior = null; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 85c74ab472b10..71918229600a0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -626,14 +626,12 @@ public function testThrowsExceptionWhenSetServiceOnAFrozenContainer() $container->set('a', new \stdClass()); } - /** - * @expectedException \BadMethodCallException - */ public function testThrowsExceptionWhenAddServiceOnAFrozenContainer() { $container = new ContainerBuilder(); $container->compile(); - $container->set('a', new \stdClass()); + $container->set('a', $foo = new \stdClass()); + $this->assertSame($foo, $container->get('a')); } public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer() diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index a81118e498383..0fbeb36293d0a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -208,6 +208,18 @@ public function testGetCircularReference() } } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage You have requested a synthetic service ("request"). The DIC does not know how to construct this service. + */ + public function testGetSyntheticServiceAlwaysThrows() + { + require_once __DIR__.'/Fixtures/php/services9.php'; + + $container = new \ProjectServiceContainer(); + $container->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE); + } + public function testHas() { $sc = new ProjectServiceContainer(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index 35bc048c11626..6a85f8044bde6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -159,7 +159,7 @@ public function testSetIsDeprecated() /** * @dataProvider invalidDeprecationMessageProvider - * @expectedException Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException */ public function testSetDeprecatedWithInvalidDeprecationTemplate($message) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index d155a9ac763e2..180658082a09e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -189,7 +189,7 @@ public function testConflictingMethodsWithParent() /** * @dataProvider provideInvalidFactories - * @expectedException Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException * @expectedExceptionMessage Cannot dump definition */ public function testInvalidFactories($factory) diff --git a/src/Symfony/Component/ExpressionLanguage/TokenStream.php b/src/Symfony/Component/ExpressionLanguage/TokenStream.php index ac9599769fa9c..6c4af745b2cfe 100644 --- a/src/Symfony/Component/ExpressionLanguage/TokenStream.php +++ b/src/Symfony/Component/ExpressionLanguage/TokenStream.php @@ -60,6 +60,10 @@ public function next() /** * Tests a token. + * + * @param array|int $type The type to test + * @param string|null $value The token value + * @param string|null $message The syntax error message */ public function expect($type, $value = null, $message = null) { diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 72ab9bf8cf17e..c934d83bf66d5 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -285,6 +285,8 @@ public function rename($origin, $target, $overwrite = false) * * @param string $filename Path to the file * + * @return bool + * * @throws IOException When windows path is longer than 258 characters */ private function isReadable($filename) @@ -554,8 +556,7 @@ public function dumpFile($filename, $content) throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); } - // Ignore for filesystems that do not support umask - @chmod($tmpFile, 0666); + @chmod($tmpFile, 0666 & ~umask()); $this->rename($tmpFile, $filename, true); } diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 9a65543098d76..58523c22154cc 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1101,13 +1101,19 @@ public function testDumpFile() { $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt'; + // skip mode check on Windows + if ('\\' !== DIRECTORY_SEPARATOR) { + $oldMask = umask(0002); + } + $this->filesystem->dumpFile($filename, 'bar'); $this->assertFileExists($filename); $this->assertSame('bar', file_get_contents($filename)); // skip mode check on Windows if ('\\' !== DIRECTORY_SEPARATOR) { - $this->assertFilePermissions(666, $filename); + $this->assertFilePermissions(664, $filename); + umask($oldMask); } } 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 14d9511f6cdad..5bea38e69a772 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/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index f027ea3290043..dbf8f36b97132 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -177,12 +177,13 @@ public function getValuesForChoices(array $choices) /** * Flattens an array into the given output variables. * - * @param array $choices The array to flatten - * @param callable $value The callable for generating choice values - * @param array $choicesByValues The flattened choices indexed by the - * corresponding values - * @param array $keysByValues The original keys indexed by the - * corresponding values + * @param array $choices The array to flatten + * @param callable $value The callable for generating choice values + * @param array $choicesByValues The flattened choices indexed by the + * corresponding values + * @param array $keysByValues The original keys indexed by the + * corresponding values + * @param array $structuredValues The values indexed by the original keys * * @internal Must not be used by user-land code */ diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 4e15feb148a51..8434f8932bab1 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -133,7 +133,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); } @@ -177,8 +180,6 @@ protected function getIntlDateFormatter($ignoreTimezone = false) /** * Checks if the pattern contains only a date. * - * @param string $pattern The input pattern - * * @return bool */ protected function isPatternDateOnly() diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php index ff8d0b4fdecf7..86894f1adc6bf 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php @@ -142,6 +142,13 @@ public function configureOptions(OptionsResolver $resolver) }; }; + // Wrap "post_max_size_message" in a closure to translate it lazily + $uploadMaxSizeMessage = function (Options $options) { + return function () use ($options) { + return $options['post_max_size_message']; + }; + }; + // For any form that is not represented by a single HTML control, // errors should bubble up by default $errorBubbling = function (Options $options) { @@ -172,9 +179,11 @@ public function configureOptions(OptionsResolver $resolver) 'action' => '', 'attr' => array(), 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', + 'upload_max_size_message' => $uploadMaxSizeMessage, // internal )); $resolver->setAllowedTypes('label_attr', 'array'); + $resolver->setAllowedTypes('upload_max_size_message', array('callable')); } /** diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php index ec89c883643cd..fbb28b1bc0741 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php @@ -23,14 +23,8 @@ */ class FormDataExtractor implements FormDataExtractorInterface { - /** - * @var ValueExporter - */ private $valueExporter; - /** - * Constructs a new data extractor. - */ public function __construct(ValueExporter $valueExporter = null) { $this->valueExporter = $valueExporter ?: new ValueExporter(); diff --git a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php index d1e5eece7b5a4..004f4778f98a0 100644 --- a/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -78,7 +78,7 @@ public function handleRequest(FormInterface $form, $request = null) $form->submit(null, false); $form->addError(new FormError( - $form->getConfig()->getOption('post_max_size_message'), + call_user_func($form->getConfig()->getOption('upload_max_size_message')), null, array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()) )); diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php index 606c3fa5d4911..9abb14189dc0e 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php @@ -18,8 +18,8 @@ */ class Form extends Constraint { - const NOT_SYNCHRONIZED_ERROR = 1; - const NO_SUCH_FIELD_ERROR = 2; + const NOT_SYNCHRONIZED_ERROR = '1dafa156-89e1-4736-b832-419c2e501fca'; + const NO_SUCH_FIELD_ERROR = '6e5212ed-a197-4339-99aa-5654798a4854'; protected static $errorNames = array( self::NOT_SYNCHRONIZED_ERROR => 'NOT_SYNCHRONIZED_ERROR', diff --git a/src/Symfony/Component/Form/Extension/Validator/Type/UploadValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/Type/UploadValidatorExtension.php index d89a326f77a10..6f1f632118c81 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Type/UploadValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/Type/UploadValidatorExtension.php @@ -42,9 +42,10 @@ public function configureOptions(OptionsResolver $resolver) { $translator = $this->translator; $translationDomain = $this->translationDomain; - - $resolver->setNormalizer('post_max_size_message', function (Options $options, $errorMessage) use ($translator, $translationDomain) { - return $translator->trans($errorMessage, array(), $translationDomain); + $resolver->setNormalizer('upload_max_size_message', function (Options $options, $message) use ($translator, $translationDomain) { + return function () use ($translator, $translationDomain, $message) { + return $translator->trans(call_user_func($message), array(), $translationDomain); + }; }); } 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/NativeRequestHandler.php b/src/Symfony/Component/Form/NativeRequestHandler.php index 5541e96ad5df3..3607feb99cc98 100644 --- a/src/Symfony/Component/Form/NativeRequestHandler.php +++ b/src/Symfony/Component/Form/NativeRequestHandler.php @@ -86,7 +86,7 @@ public function handleRequest(FormInterface $form, $request = null) $form->submit(null, false); $form->addError(new FormError( - $form->getConfig()->getOption('post_max_size_message'), + call_user_func($form->getConfig()->getOption('upload_max_size_message')), null, array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()) )); diff --git a/src/Symfony/Component/Form/PreloadedExtension.php b/src/Symfony/Component/Form/PreloadedExtension.php index 5b49e353b7874..c9ab2bccaf961 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 8e337268964de..25edbed147103 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -620,8 +620,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 1ac2dc5ea9f03..b54c0d50ef74f 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/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index c51132518ba67..3295e3d85fe8c 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -108,10 +108,10 @@ public function testReverseTransformEmpty() public function testReverseTransformWithGrouping() { - // Since we test against "de_AT", we need the full implementation + // Since we test against "de_DE", we need the full implementation IntlTestHelper::requireFullIntl($this); - \Locale::setDefault('de_AT'); + \Locale::setDefault('de_DE'); $transformer = new IntegerToLocalizedStringTransformer(null, true); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 2ea4e9dd2a8f4..ab58d3685d774 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -54,8 +54,8 @@ public function testTransform($from, $to, $locale) public function provideTransformationsWithGrouping() { return array( - array(1234.5, '1.234,5', 'de_AT'), - array(12345.912, '12.345,912', 'de_AT'), + array(1234.5, '1.234,5', 'de_DE'), + array(12345.912, '12.345,912', 'de_DE'), array(1234.5, '1 234,5', 'fr'), array(1234.5, '1 234,5', 'ru'), array(1234.5, '1 234,5', 'fi'), @@ -393,10 +393,10 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { - // Since we test against "de_AT", we need the full implementation + // Since we test against "de_DE", we need the full implementation IntlTestHelper::requireFullIntl($this); - \Locale::setDefault('de_AT'); + \Locale::setDefault('de_DE'); $transformer = new NumberToLocalizedStringTransformer(null, true); @@ -408,10 +408,10 @@ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() { - // Since we test against "de_AT", we need the full implementation + // Since we test against "de_DE", we need the full implementation IntlTestHelper::requireFullIntl($this); - \Locale::setDefault('de_AT'); + \Locale::setDefault('de_DE'); $transformer = new NumberToLocalizedStringTransformer(null, true); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php index 95a11a78c71ce..dbe13a27456f6 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\Extension\Validator\Type\UploadValidatorExtension; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\OptionsResolver\Options; class UploadValidatorExtensionTest extends TypeTestCase { @@ -29,10 +30,15 @@ public function testPostMaxSizeTranslation() $resolver = new OptionsResolver(); $resolver->setDefault('post_max_size_message', 'old max {{ max }}!'); + $resolver->setDefault('upload_max_size_message', function (Options $options, $message) { + return function () use ($options) { + return $options['post_max_size_message']; + }; + }); $extension->configureOptions($resolver); $options = $resolver->resolve(); - $this->assertEquals('translated max {{ max }}!', $options['post_max_size_message']); + $this->assertEquals('translated max {{ max }}!', call_user_func($options['upload_max_size_message'])); } } diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index daacb82a449ef..c183372e2d9c3 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -27,7 +27,7 @@ class JsonResponse extends Response protected $data; protected $callback; - // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML. + // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT const DEFAULT_ENCODING_OPTIONS = 15; @@ -51,7 +51,18 @@ public function __construct($data = null, $status = 200, $headers = array(), $js } /** - * {@inheritdoc} + * Factory method for chainability. + * + * Example: + * + * return JsonResponse::create($data, 200) + * ->setSharedMaxAge(300); + * + * @param mixed $data The json response data + * @param int $status The response status code + * @param array $headers An array of response headers + * + * @return JsonResponse */ public static function create($data = null, $status = 200, $headers = array()) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php index 80e97f17cdff3..25f3d57b5417b 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php @@ -72,6 +72,8 @@ public function all(); /** * Sets all flash messages. + * + * @param array $messages */ public function setAll(array $messages); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 7efc1348c8027..8408f000cdbf8 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -214,6 +214,8 @@ protected function getMongo() * Return an instance of a MongoDate or \MongoDB\BSON\UTCDateTime * * @param int $seconds An integer representing UTC seconds since Jan 1 1970. Defaults to now. + * + * @return \MongoDate|\MongoDB\BSON\UTCDateTime */ private function createDateTime($seconds = null) { 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/ArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php index 1d8a0410ebbc1..049f89980035e 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php @@ -79,7 +79,7 @@ public function getArguments(Request $request, $controller) $representative = get_class($representative); } - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $representative, $metadata->getName())); + throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); } return $arguments; diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/DefaultValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/DefaultValueResolver.php index 5dd7c772b27ab..0962dab885fe9 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/DefaultValueResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/DefaultValueResolver.php @@ -27,7 +27,7 @@ final class DefaultValueResolver implements ArgumentValueResolverInterface */ public function supports(Request $request, ArgumentMetadata $argument) { - return $argument->hasDefaultValue(); + return $argument->hasDefaultValue() || $argument->isNullable(); } /** @@ -35,6 +35,6 @@ public function supports(Request $request, ArgumentMetadata $argument) */ public function resolve(Request $request, ArgumentMetadata $argument) { - yield $argument->getDefaultValue(); + yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; } } diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 084d732ef4a8c..f5fe436379841 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -27,6 +27,15 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve { 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 ArgumentResolverInterface, ControllerResolve public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; + + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); } /** @@ -104,6 +115,12 @@ public function getArguments(Request $request, $controller) } /** + * @param Request $request + * @param callable $controller + * @param \ReflectionParameter[] $parameters + * + * @return array The arguments to use when calling the action + * * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead. */ protected function doGetArguments(Request $request, $controller, array $parameters) @@ -114,7 +131,7 @@ protected function doGetArguments(Request $request, $controller, array $paramete $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]; @@ -123,6 +140,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/ControllerMetadata/ArgumentMetadata.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadata.php index ca0e881fefbb3..72c294f3a3d7c 100644 --- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadata.php +++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadata.php @@ -23,6 +23,7 @@ class ArgumentMetadata private $isVariadic; private $hasDefaultValue; private $defaultValue; + private $isNullable; /** * @param string $name @@ -30,14 +31,16 @@ class ArgumentMetadata * @param bool $isVariadic * @param bool $hasDefaultValue * @param mixed $defaultValue + * @param bool $isNullable */ - public function __construct($name, $type, $isVariadic, $hasDefaultValue, $defaultValue) + public function __construct($name, $type, $isVariadic, $hasDefaultValue, $defaultValue, $isNullable = false) { $this->name = $name; $this->type = $type; $this->isVariadic = $isVariadic; $this->hasDefaultValue = $hasDefaultValue; $this->defaultValue = $defaultValue; + $this->isNullable = (bool) $isNullable; } /** @@ -84,6 +87,16 @@ public function hasDefaultValue() return $this->hasDefaultValue; } + /** + * Returns whether the argument is nullable in PHP 7.1 or higher. + * + * @return bool + */ + public function isNullable() + { + return $this->isNullable; + } + /** * Returns the default value of the argument. * diff --git a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php index 6f49f389321d3..efe5966894495 100644 --- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -18,6 +18,30 @@ */ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface { + /** + * If the ...$arg functionality is available. + * + * Requires at least PHP 5.6.0 or HHVM 3.9.1 + * + * @var bool + */ + private $supportsVariadic; + + /** + * If the reflection supports the getType() method to resolve types. + * + * Requires at least PHP 7.0.0 or HHVM 3.11.0 + * + * @var bool + */ + private $supportsParameterType; + + public function __construct() + { + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); + $this->supportsParameterType = method_exists('ReflectionParameter', 'getType'); + } + /** * {@inheritdoc} */ @@ -34,7 +58,7 @@ public function createArgumentMetadata($controller) } foreach ($reflection->getParameters() as $param) { - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param)); + $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $this->isNullable($param)); } return $arguments; @@ -49,7 +73,7 @@ public function createArgumentMetadata($controller) */ private function isVariadic(\ReflectionParameter $parameter) { - return PHP_VERSION_ID >= 50600 && $parameter->isVariadic(); + return $this->supportsVariadic && $parameter->isVariadic(); } /** @@ -64,6 +88,23 @@ private function hasDefaultValue(\ReflectionParameter $parameter) return $parameter->isDefaultValueAvailable(); } + /** + * Returns if the argument is allowed to be null but is still mandatory. + * + * @param \ReflectionParameter $parameter + * + * @return bool + */ + private function isNullable(\ReflectionParameter $parameter) + { + if ($this->supportsParameterType) { + return null !== ($type = $parameter->getType()) && $type->allowsNull(); + } + + // fallback for supported php 5.x versions + return $this->hasDefaultValue($parameter) && null === $this->getDefaultValue($parameter); + } + /** * Returns a default value if available. * @@ -85,7 +126,7 @@ private function getDefaultValue(\ReflectionParameter $parameter) */ private function getType(\ReflectionParameter $parameter) { - if (PHP_VERSION_ID >= 70000) { + if ($this->supportsParameterType) { return $parameter->hasType() ? (string) $parameter->getType() : null; } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 0977029cd7d64..0e4df12baa8d7 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -168,6 +168,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/DependencyInjection/LazyLoadingFragmentHandler.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php index 7899562376660..3559e39e9001d 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php @@ -42,6 +42,7 @@ public function __construct(ContainerInterface $container, RequestStack $request /** * Adds a service as a fragment renderer. * + * @param string $name The service name * @param string $renderer The render service id */ public function addRendererService($name, $renderer) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 28c18dcbab8ae..f3a22fa06ab57 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,11 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.1.4'; - const VERSION_ID = 30104; + const VERSION = '3.1.5'; + const VERSION_ID = 30105; const MAJOR_VERSION = 3; const MINOR_VERSION = 1; - const RELEASE_VERSION = 4; + const RELEASE_VERSION = 5; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2017'; diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index af0721f57e899..f31e243770cbf 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -78,7 +78,7 @@ public function enable() * * @param Response $response A Response instance * - * @return Profile A Profile instance + * @return Profile|false A Profile instance */ public function loadProfileFromResponse(Response $response) { diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php index 3f647e0bba437..964d83236278e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php @@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest; +use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; @@ -202,6 +203,32 @@ public function testGetArgumentWithoutArray() $resolver->getArguments($request, $controller); } + /** + * @requires PHP 7.1 + */ + public function testGetNullableArguments() + { + $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'), self::$resolver->getArguments($request, $controller)); + } + + /** + * @requires PHP 7.1 + */ + public function testGetNullableArgumentsWithDefaults() + { + $request = Request::create('/'); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + + $this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller)); + } + public function __invoke($foo, $bar = null) { } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 7daf0daa2977f..a1b9a1c78d857 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; @@ -226,6 +227,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/ControllerMetadata/ArgumentMetadataFactoryTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php index c6c2b597b1e5b..49931f052c82e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php @@ -15,10 +15,14 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\BasicTypesController; +use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; class ArgumentMetadataFactoryTest extends \PHPUnit_Framework_TestCase { + /** + * @var ArgumentMetadataFactory + */ private $factory; protected function setUp() @@ -42,9 +46,9 @@ public function testSignature2() $arguments = $this->factory->createArgumentMetadata(array($this, 'signature2')); $this->assertEquals(array( - new ArgumentMetadata('foo', self::class, false, true, null), - new ArgumentMetadata('bar', __NAMESPACE__.'\FakeClassThatDoesNotExist', false, true, null), - new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, true, null), + new ArgumentMetadata('foo', self::class, false, true, null, true), + new ArgumentMetadata('bar', __NAMESPACE__.'\FakeClassThatDoesNotExist', false, true, null, true), + new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, true, null, true), ), $arguments); } @@ -74,7 +78,7 @@ public function testSignature5() $arguments = $this->factory->createArgumentMetadata(array($this, 'signature5')); $this->assertEquals(array( - new ArgumentMetadata('foo', 'array', false, true, null), + new ArgumentMetadata('foo', 'array', false, true, null, true), new ArgumentMetadata('bar', null, false, false, null), ), $arguments); } @@ -106,6 +110,21 @@ public function testBasicTypesSignature() ), $arguments); } + /** + * @requires PHP 7.1 + */ + public function testNullableTypesSignature() + { + $arguments = $this->factory->createArgumentMetadata(array(new NullableController(), 'action')); + + $this->assertEquals(array( + new ArgumentMetadata('foo', 'string', false, false, null, true), + new ArgumentMetadata('bar', \stdClass::class, false, false, null, true), + new ArgumentMetadata('baz', 'string', false, true, 'value', true), + new ArgumentMetadata('mandatory', null, false, false, null), + ), $arguments); + } + private function signature1(ArgumentMetadataFactoryTest $foo, array $bar, callable $baz) { } diff --git a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataTest.php index 9713d70f8e649..cbb0d1bece382 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataTest.php @@ -15,10 +15,18 @@ class ArgumentMetadataTest extends \PHPUnit_Framework_TestCase { - public function testDefaultValueAvailable() + public function testWithBcLayerWithDefault() { $argument = new ArgumentMetadata('foo', 'string', false, true, 'default value'); + $this->assertFalse($argument->isNullable()); + } + + public function testDefaultValueAvailable() + { + $argument = new ArgumentMetadata('foo', 'string', false, true, 'default value', true); + + $this->assertTrue($argument->isNullable()); $this->assertTrue($argument->hasDefaultValue()); $this->assertSame('default value', $argument->getDefaultValue()); } @@ -28,8 +36,9 @@ public function testDefaultValueAvailable() */ public function testDefaultValueUnavailable() { - $argument = new ArgumentMetadata('foo', 'string', false, false, null); + $argument = new ArgumentMetadata('foo', 'string', false, false, null, false); + $this->assertFalse($argument->isNullable()); $this->assertFalse($argument->hasDefaultValue()); $argument->getDefaultValue(); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 14db808b4f9e6..49890ebff146e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -82,10 +82,9 @@ public function testCollectHtml() $line = __LINE__ - 1; $file = __FILE__; $xOutput = <<DumpDataCollectorTest.php on line {$line}: +
DumpDataCollectorTest.php on line {$line}:
 123
 
- EOTXT; ob_start(); @@ -96,7 +95,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/EventListener/ValidateRequestListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php index 842a3869cba79..b9d8f06f00848 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php @@ -21,7 +21,7 @@ class ValidateRequestListenerTest extends \PHPUnit_Framework_TestCase { /** - * @expectedException Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException + * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException */ public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps() { 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/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 8587aa3aae621..ee3d999361f8c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -303,7 +303,7 @@ public function testVerifyRequestStackPushPopDuringHandle() } /** - * @expectedException Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException */ public function testInconsistentClientIpsOnMasterRequests() { diff --git a/src/Symfony/Component/HttpKernel/UriSigner.php b/src/Symfony/Component/HttpKernel/UriSigner.php index c2d0d79664c42..fa84899064e88 100644 --- a/src/Symfony/Component/HttpKernel/UriSigner.php +++ b/src/Symfony/Component/HttpKernel/UriSigner.php @@ -98,7 +98,7 @@ private function buildUrl(array $url, array $params = array()) $host = isset($url['host']) ? $url['host'] : ''; $port = isset($url['port']) ? ':'.$url['port'] : ''; $user = isset($url['user']) ? $url['user'] : ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; + $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = isset($url['path']) ? $url['path'] : ''; $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : ''; diff --git a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php index 592969475ec4e..e689638573235 100644 --- a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php +++ b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php @@ -550,7 +550,7 @@ public function setTimeZoneId($timeZoneId) try { $this->dateTimeZone = new \DateTimeZone($timeZoneId); if ('GMT' !== $timeZoneId && $this->dateTimeZone->getName() !== $timeZoneId) { - $timeZoneId = $timeZone = $this->getTimeZoneId(); + $timeZone = $this->getTimeZoneId(); } } catch (\Exception $e) { $timeZoneId = $timeZone = $this->getTimeZoneId(); diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php index cfe82ca3c3135..d12b892a10dcb 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php @@ -42,6 +42,7 @@ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInter * @param string $path * @param BundleEntryReaderInterface $reader * @param LocaleDataProvider $localeProvider + * @param ScriptDataProvider $scriptProvider */ public function __construct($path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider, ScriptDataProvider $scriptProvider) { diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php index 07eff73907f1b..d9b2dd4f5d4ea 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php @@ -24,11 +24,10 @@ class Collection implements CollectionInterface private $search; private $entries; - public function __construct(Connection $connection, Query $search, array $entries = array()) + public function __construct(Connection $connection, Query $search) { $this->connection = $connection; $this->search = $search; - $this->entries = array(); } /** @@ -36,78 +35,91 @@ public function __construct(Connection $connection, Query $search, array $entrie */ public function toArray() { - $this->initialize(); + if (null === $this->entries) { + $this->entries = iterator_to_array($this->getIterator(), false); + } return $this->entries; } public function count() { - $this->initialize(); + if (false !== $count = ldap_count_entries($this->connection->getResource(), $this->search->getResource())) { + return $count; + } - return count($this->entries); + throw new LdapException(sprintf('Error while retrieving entry count: %s', ldap_error($this->connection->getResource()))); } public function getIterator() { - return new ResultIterator($this->connection, $this->search); + $con = $this->connection->getResource(); + $search = $this->search->getResource(); + $current = ldap_first_entry($con, $search); + + if (0 === $this->count()) { + return; + } + + if (false === $current) { + throw new LdapException(sprintf('Could not rewind entries array: %s', ldap_error($con))); + } + + yield $this->getSingleEntry($con, $current); + + while (false !== $current = ldap_next_entry($con, $current)) { + yield $this->getSingleEntry($con, $current); + } } public function offsetExists($offset) { - $this->initialize(); + $this->toArray(); return isset($this->entries[$offset]); } public function offsetGet($offset) { + $this->toArray(); + return isset($this->entries[$offset]) ? $this->entries[$offset] : null; } public function offsetSet($offset, $value) { - $this->initialize(); + $this->toArray(); $this->entries[$offset] = $value; } public function offsetUnset($offset) { - $this->initialize(); + $this->toArray(); unset($this->entries[$offset]); } - private function initialize() + private function getSingleEntry($con, $current) { - if (null === $this->entries) { - return; - } + $attributes = ldap_get_attributes($con, $current); - $con = $this->connection->getResource(); - - $entries = ldap_get_entries($con, $this->search->getResource()); - - if (false === $entries) { - throw new LdapException(sprintf('Could not load entries: %s', ldap_error($con))); + if (false === $attributes) { + throw new LdapException(sprintf('Could not fetch attributes: %s', ldap_error($con))); } - if (0 === $entries['count']) { - return array(); - } + $attributes = $this->cleanupAttributes($attributes); - unset($entries['count']); + $dn = ldap_get_dn($con, $current); - $this->entries = array_map(function (array $entry) { - $dn = $entry['dn']; - $attributes = $this->cleanupAttributes($entry); + if (false === $dn) { + throw new LdapException(sprintf('Could not fetch DN: %s', ldap_error($con))); + } - return new Entry($dn, $attributes); - }, $entries); + return new Entry($dn, $attributes); } - private function cleanupAttributes(array $entry = array()) + private function cleanupAttributes(array $entry) { $attributes = array_diff_key($entry, array_flip(range(0, $entry['count'] - 1)) + array( 'count' => null, diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/ResultIterator.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/ResultIterator.php deleted file mode 100644 index 2527069c5b0a1..0000000000000 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/ResultIterator.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Ldap\Adapter\ExtLdap; - -use Symfony\Component\Ldap\Entry; -use Symfony\Component\Ldap\Exception\LdapException; - -/** - * @author Charles Sarrazin - * - * @internal - */ -class ResultIterator implements \Iterator -{ - private $connection; - private $search; - private $current; - private $key; - - public function __construct(Connection $connection, Query $search) - { - $this->connection = $connection->getResource(); - $this->search = $search->getResource(); - } - - /** - * Fetches the current entry. - * - * @return Entry - */ - public function current() - { - $attributes = ldap_get_attributes($this->connection, $this->current); - - if (false === $attributes) { - throw new LdapException(sprintf('Could not fetch attributes: %s', ldap_error($this->connection))); - } - - $dn = ldap_get_dn($this->connection, $this->current); - - if (false === $dn) { - throw new LdapException(sprintf('Could not fetch DN: %s', ldap_error($this->connection))); - } - - return new Entry($dn, $attributes); - } - - public function next() - { - $this->current = ldap_next_entry($this->connection, $this->current); - ++$this->key; - } - - public function key() - { - return $this->key; - } - - public function valid() - { - return false !== $this->current; - } - - public function rewind() - { - $this->current = ldap_first_entry($this->connection, $this->search); - - if (false === $this->current) { - throw new LdapException(sprintf('Could not rewind entries array: %s', ldap_error($this->connection))); - } - } -} diff --git a/src/Symfony/Component/Ldap/LdapClient.php b/src/Symfony/Component/Ldap/LdapClient.php index 2bd32f6ac1066..0a68c05875b78 100644 --- a/src/Symfony/Component/Ldap/LdapClient.php +++ b/src/Symfony/Component/Ldap/LdapClient.php @@ -64,24 +64,34 @@ public function find($dn, $query, $filter = '*') $query = $this->ldap->query($dn, $query, array('filter' => $filter)); $entries = $query->execute(); - $result = array(); + $result = array( + 'count' => 0, + ); foreach ($entries as $entry) { $resultEntry = array(); foreach ($entry->getAttributes() as $attribute => $values) { - $resultAttribute = $values; + $resultAttribute = array( + 'count' => count($values), + ); + + foreach ($values as $val) { + $resultAttribute[] = $val; + } + $attributeName = strtolower($attribute); $resultAttribute['count'] = count($values); - $resultEntry[] = $resultAttribute; - $resultEntry[$attribute] = $resultAttribute; + $resultEntry[$attributeName] = $resultAttribute; + $resultEntry[] = $attributeName; } $resultEntry['count'] = count($resultEntry) / 2; + $resultEntry['dn'] = $entry->getDn(); $result[] = $resultEntry; } - $result['count'] = count($result); + $result['count'] = count($result) - 1; return $result; } diff --git a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php index df30ec85a2ac6..f25d181896d35 100644 --- a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php +++ b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/AdapterTest.php @@ -47,4 +47,22 @@ public function testLdapQuery() $this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn')); $this->assertEquals(array('fabpot@symfony.com', 'fabien@potencier.com'), $entry->getAttribute('mail')); } + + /** + * @group functional + */ + public function testLdapQueryIterator() + { + $ldap = new Adapter($this->getLdapConfig()); + + $ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony'); + $query = $ldap->createQuery('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array()); + $result = $query->execute(); + $iterator = $result->getIterator(); + $iterator->rewind(); + $entry = $iterator->current(); + $this->assertInstanceOf(Entry::class, $entry); + $this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn')); + $this->assertEquals(array('fabpot@symfony.com', 'fabien@potencier.com'), $entry->getAttribute('mail')); + } } diff --git a/src/Symfony/Component/Ldap/Tests/LdapClientTest.php b/src/Symfony/Component/Ldap/Tests/LdapClientTest.php index 60cdf27a1231f..30c5adfd40b1f 100644 --- a/src/Symfony/Component/Ldap/Tests/LdapClientTest.php +++ b/src/Symfony/Component/Ldap/Tests/LdapClientTest.php @@ -20,7 +20,7 @@ /** * @group legacy */ -class LdapClientTest extends \PHPUnit_Framework_TestCase +class LdapClientTest extends LdapTestCase { /** @var LdapClient */ private $client; @@ -72,13 +72,11 @@ public function testLdapFind() ->method('getIterator') ->will($this->returnValue(new \ArrayIterator(array( new Entry('cn=qux,dc=foo,dc=com', array( - 'dn' => array('cn=qux,dc=foo,dc=com'), 'cn' => array('qux'), 'dc' => array('com', 'foo'), 'givenName' => array('Qux'), )), new Entry('cn=baz,dc=foo,dc=com', array( - 'dn' => array('cn=baz,dc=foo,dc=com'), 'cn' => array('baz'), 'dc' => array('com', 'foo'), 'givenName' => array('Baz'), @@ -101,78 +99,44 @@ public function testLdapFind() $expected = array( 'count' => 2, 0 => array( - 'count' => 4, - 0 => array( - 'count' => 1, - 0 => 'cn=qux,dc=foo,dc=com', - ), - 'dn' => array( - 'count' => 1, - 0 => 'cn=qux,dc=foo,dc=com', - ), - 1 => array( - 'count' => 1, - 0 => 'qux', - ), + 'count' => 3, + 0 => 'cn', 'cn' => array( 'count' => 1, 0 => 'qux', ), - 2 => array( - 'count' => 2, - 0 => 'com', - 1 => 'foo', - ), + 1 => 'dc', 'dc' => array( 'count' => 2, 0 => 'com', 1 => 'foo', ), - 3 => array( - 'count' => 1, - 0 => 'Qux', - ), - 'givenName' => array( + 2 => 'givenname', + 'givenname' => array( 'count' => 1, 0 => 'Qux', ), + 'dn' => 'cn=qux,dc=foo,dc=com', ), 1 => array( - 'count' => 4, - 0 => array( - 'count' => 1, - 0 => 'cn=baz,dc=foo,dc=com', - ), - 'dn' => array( - 'count' => 1, - 0 => 'cn=baz,dc=foo,dc=com', - ), - 1 => array( - 'count' => 1, - 0 => 'baz', - ), + 'count' => 3, + 0 => 'cn', 'cn' => array( 'count' => 1, 0 => 'baz', ), - 2 => array( - 'count' => 2, - 0 => 'com', - 1 => 'foo', - ), + 1 => 'dc', 'dc' => array( 'count' => 2, 0 => 'com', 1 => 'foo', ), - 3 => array( - 'count' => 1, - 0 => 'Baz', - ), - 'givenName' => array( + 2 => 'givenname', + 'givenname' => array( 'count' => 1, 0 => 'Baz', ), + 'dn' => 'cn=baz,dc=foo,dc=com', ), ); $this->assertEquals($expected, $this->client->find('dc=foo,dc=com', 'bar', 'baz')); @@ -190,6 +154,25 @@ public function testLdapClientConfig($args, $expected) $this->assertEquals($expected, call_user_func_array(array($reflMethod, 'invoke'), $args)); } + /** + * @group functional + * @requires extension ldap + */ + public function testLdapClientFunctional() + { + $config = $this->getLdapConfig(); + $ldap = new LdapClient($config['host'], $config['port']); + $ldap->bind('cn=admin,dc=symfony,dc=com', 'symfony'); + $result = $ldap->find('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))'); + + $con = @ldap_connect($config['host'], $config['port']); + @ldap_bind($con, 'cn=admin,dc=symfony,dc=com', 'symfony'); + $search = @ldap_search($con, 'dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array('*')); + $expected = @ldap_get_entries($con, $search); + + $this->assertSame($expected, $result); + } + public function provideConfig() { return array( 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/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 317b5ef69f0f1..cd57f3a8c32df 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -939,7 +939,7 @@ public function provideMethodsThatNeedARunningProcess() /** * @dataProvider provideMethodsThatNeedATerminatedProcess - * @expectedException Symfony\Component\Process\Exception\LogicException + * @expectedException \Symfony\Component\Process\Exception\LogicException * @expectedExceptionMessage Process must be terminated before calling */ public function testMethodsThatNeedATerminatedProcess($method) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 63454a5b45319..1d3d3a2083ca8 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -231,7 +231,7 @@ private function extractFromAccessor($class, $property) */ private function extractFromReflectionType(\ReflectionType $reflectionType) { - $phpTypeOrClass = (string) $reflectionType; + $phpTypeOrClass = method_exists($reflectionType, 'getName') ? $reflectionType->getName() : (string) $reflectionType; $nullable = $reflectionType->allowsNull(); if ($reflectionType->isBuiltin()) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index dfc13c025eb41..10b056220d539 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -94,6 +94,25 @@ public function php7TypesProvider() ); } + /** + * @dataProvider php71TypesProvider + * @requires PHP 7.1 + */ + public function testExtractPhp71Type($property, array $type = null) + { + $this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy', $property, array())); + } + + public function php71TypesProvider() + { + return array( + array('foo', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true))), + array('bar', array(new Type(Type::BUILTIN_TYPE_INT, true))), + array('baz', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))), + array('donotexist', null), + ); + } + public function testIsReadable() { $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'bar', array())); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php71Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php71Dummy.php new file mode 100644 index 0000000000000..d93c67a3d38bd --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php71Dummy.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +/** + * @author Teoh Han Hui + */ +class Php71Dummy +{ + public function getFoo(): ?array + { + } + + public function setBar(?int $bar) + { + } + + public function addBaz(string $baz) + { + } +} diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/Voter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/Voter.php index ba4d6af5a8b56..0641486b7a13b 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/Voter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/Voter.php @@ -58,6 +58,7 @@ abstract protected function supports($attribute, $subject); /** * Perform a single access check operation on a given attribute, subject and token. + * It is safe to assume that $attribute and $subject already passed the "supports()" method check. * * @param string $attribute * @param mixed $subject 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/Core/Role/RoleHierarchy.php b/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php index 793007e7f5420..95e76ee279316 100644 --- a/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php +++ b/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php @@ -65,9 +65,17 @@ protected function buildRoleMap() } $visited[] = $role; - $this->map[$main] = array_unique(array_merge($this->map[$main], $this->hierarchy[$role])); - $additionalRoles = array_merge($additionalRoles, array_diff($this->hierarchy[$role], $visited)); + + foreach ($this->hierarchy[$role] as $roleToAdd) { + $this->map[$main][] = $roleToAdd; + } + + foreach (array_diff($this->hierarchy[$role], $visited) as $additionalRole) { + $additionalRoles[] = $additionalRole; + } } + + $this->map[$main] = array_unique($this->map[$main]); } } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php index 7309042d4764b..cd2f1b8735b86 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php @@ -101,7 +101,7 @@ public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenti } /** - * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException * @expectedExceptionMessage Authentication failed. */ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExceptionThrownAuthenticationManagerImplementation() 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/Serializer/Tests/Encoder/ChainDecoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php index 7f7392e6a45b1..a6d3f40f2366d 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/ChainDecoderTest.php @@ -68,7 +68,7 @@ public function testDecode() } /** - * @expectedException Symfony\Component\Serializer\Exception\RuntimeException + * @expectedException \Symfony\Component\Serializer\Exception\RuntimeException */ public function testDecodeUnsupportedFormat() { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php index 6d3436b33d753..4fc6b25f9b47f 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/ChainEncoderTest.php @@ -69,7 +69,7 @@ public function testEncode() } /** - * @expectedException Symfony\Component\Serializer\Exception\RuntimeException + * @expectedException \Symfony\Component\Serializer\Exception\RuntimeException */ public function testEncodeUnsupportedFormat() { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php index 97930115748d2..c87ab21b510a2 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php @@ -57,7 +57,7 @@ public function decodeProvider() /** * @requires function json_last_error_msg * @dataProvider decodeProviderException - * @expectedException Symfony\Component\Serializer\Exception\UnexpectedValueException + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function testDecodeWithException($value) { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php index 3e6fb7b6ec34e..d255b21d22e7f 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php @@ -50,7 +50,7 @@ public function encodeProvider() /** * @requires function json_last_error_msg - * @expectedException Symfony\Component\Serializer\Exception\UnexpectedValueException + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function testEncodeWithError() { diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index ca1c4e0f59f82..1b3548ed56947 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -15,7 +15,6 @@ use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; @@ -546,7 +545,7 @@ public function testDenomalizeRecursive() } /** - * @expectedException UnexpectedValueException + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException * @expectedExceptionMessage The type of the "date" attribute for class "Symfony\Component\Serializer\Tests\Normalizer\ObjectOuter" must be one of "DateTimeInterface" ("string" given). */ public function testRejectInvalidType() @@ -558,7 +557,7 @@ public function testRejectInvalidType() } /** - * @expectedException UnexpectedValueException + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException * @expectedExceptionMessage The type of the key "a" must be "int" ("string" given). */ public function testRejectInvalidKey() diff --git a/src/Symfony/Component/Templating/PhpEngine.php b/src/Symfony/Component/Templating/PhpEngine.php index 0d34d9d384a6c..41b7daef4e18d 100644 --- a/src/Symfony/Component/Templating/PhpEngine.php +++ b/src/Symfony/Component/Templating/PhpEngine.php @@ -142,6 +142,7 @@ protected function evaluate(Storage $template, array $parameters = array()) throw new \InvalidArgumentException('Invalid parameter (view)'); } + // the view variable is exposed to the require file below $view = $this; if ($this->evalTemplate instanceof FileStorage) { extract($this->evalParameters, EXTR_SKIP); diff --git a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php index f9aae42d8c810..00a33d253a9a9 100644 --- a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php @@ -26,7 +26,7 @@ class MoFileDumper extends FileDumper */ public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array()) { - $output = $sources = $targets = $sourceOffsets = $targetOffsets = ''; + $sources = $targets = $sourceOffsets = $targetOffsets = ''; $offsets = array(); $size = 0; diff --git a/src/Symfony/Component/Translation/Loader/MoFileLoader.php b/src/Symfony/Component/Translation/Loader/MoFileLoader.php index 2fcada28477a7..025fcd89cc12c 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -80,7 +80,7 @@ protected function loadResource($resource) $messages = array(); for ($i = 0; $i < $count; ++$i) { - $singularId = $pluralId = null; + $pluralId = null; $translated = null; fseek($stream, $offsetId + $i * 8); diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 4d6ab3eaac1db..fc5288d13bee7 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/GroupSequence.php b/src/Symfony/Component/Validator/Constraints/GroupSequence.php index 8a9627b016f96..7e85e2a07b36d 100644 --- a/src/Symfony/Component/Validator/Constraints/GroupSequence.php +++ b/src/Symfony/Component/Validator/Constraints/GroupSequence.php @@ -17,7 +17,7 @@ * When validating a group sequence, each group will only be validated if all * of the previous groups in the sequence succeeded. For example: * - * $validator->validate($address, null, new GroupSequence('Basic', 'Strict')); + * $validator->validate($address, null, new GroupSequence(array('Basic', 'Strict'))); * * In the first step, all constraints that belong to the group "Basic" will be * validated. If none of the constraints fail, the validator will then validate diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 9e6ce84644d64..7c998f530dab2 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -24,13 +24,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 20fe358678a34..f5894f49b093a 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -114,9 +114,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 22f440cfa502b..0d43d6ce26c0a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php @@ -215,7 +215,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 1a8c9d52c93ad..041aeedb49f47 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -84,6 +84,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 cbe563bfebf8d..b93146b06d159 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/Validator/Tests/Validator/AbstractTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php index 3b13c09618f36..1141779ca3551 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php @@ -37,6 +37,7 @@ abstract class AbstractTest extends AbstractValidatorTest /** * @param MetadataFactoryInterface $metadataFactory + * @param array $objectInitializers * * @return ValidatorInterface */ diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 76c069dd06be6..2780c86a41485 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -73,7 +73,7 @@ public static function castType(\ReflectionType $c, array $a, Stub $stub, $isNes $prefix = Caster::PREFIX_VIRTUAL; $a += array( - $prefix.'type' => $c->__toString(), + $prefix.'name' => method_exists('ReflectionType', 'getName') ? $c->getName() : $c->__toString(), $prefix.'allowsNull' => $c->allowsNull(), $prefix.'isBuiltin' => $c->isBuiltin(), ); @@ -157,7 +157,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']); @@ -213,12 +213,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); @@ -231,15 +232,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/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index fe1763c1a5664..6a3b451bda7f7 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -25,7 +25,6 @@ class VarCloner extends AbstractCloner protected function doClone($var) { $useExt = $this->useExt; - $i = 0; // Current iteration position in $queue $len = 1; // Length of $queue $pos = 0; // Number of cloned items past the first level $refsCounter = 0; // Hard references counter diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index 685a7ffd3a34c..f3e951f3932af 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -146,8 +146,9 @@ protected function dumpLine($depth) /** * Generic line dumper callback. * - * @param string $line The line to write - * @param int $depth The recursive depth in the dumped structure + * @param string $line The line to write + * @param int $depth The recursive depth in the dumped structure + * @param string $indentPad The line indent pad */ protected function echoLine($line, $depth, $indentPad) { diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index 0b69eac1ddbf5..d8663e84e8e3d 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); - -