diff --git a/.composer/composer.json b/.composer/composer.json
deleted file mode 100644
index d69e9f7626d55..0000000000000
--- a/.composer/composer.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "require": {
- "hirak/prestissimo": "^0.1.18"
- }
-}
diff --git a/.composer/composer.lock b/.composer/composer.lock
deleted file mode 100644
index 7027e21d9ac4b..0000000000000
--- a/.composer/composer.lock
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
- "This file is @generated automatically"
- ],
- "hash": "e02685ff7d2409d34fa87e306fc86ec5",
- "content-hash": "2854c05c76a78113c693dbbdd3f9c518",
- "packages": [
- {
- "name": "hirak/prestissimo",
- "version": "0.1.18",
- "source": {
- "type": "git",
- "url": "https://github.com/hirak/prestissimo.git",
- "reference": "84e9fb79ec18a4428c5a0c032eacac640d89be5d"
- },
- "dist": {
- "type": "zip",
- "url": "https://codeload.github.com/hirak/prestissimo/legacy.zip/84e9fb79ec18a4428c5a0c032eacac640d89be5d",
- "reference": "84e9fb79ec18a4428c5a0c032eacac640d89be5d",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "~1.0.0-alpha10",
- "ext-curl": "*",
- "php": ">=5.3.2"
- },
- "require-dev": {
- "composer/composer": "1.0.0-alpha10",
- "phpunit/phpunit": "^4.8",
- "squizlabs/php_codesniffer": "^2.5"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "Hirak\\Prestissimo\\Plugin"
- },
- "autoload": {
- "psr-4": {
- "Hirak\\Prestissimo\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Hiraku NAKANO",
- "email": "hiraku@tojiru.net"
- }
- ],
- "description": "composer parallel install plugin",
- "keywords": [
- "install",
- "parallel",
- "speedup"
- ],
- "time": "2016-03-17 13:53:53"
- }
- ],
- "packages-dev": [],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": []
-}
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 7ed7b20e228ae..71c775edb8ae7 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,6 +1,6 @@
| Q | A
| ------------- | ---
-| Branch? | "master" for new features / 2.3, 2.7, 2.8 or 3.0 for fixes
+| Branch? | "master" for new features / 2.7, 2.8, 3.0 or 3.1 for fixes
| Bug fix? | yes/no
| New feature? | yes/no
| BC breaks? | yes/no
diff --git a/.travis.php b/.travis.php
index 511e05008a335..7618c272e88ee 100644
--- a/.travis.php
+++ b/.travis.php
@@ -1,20 +1,19 @@
$_SERVER['argc']) {
- echo "Usage: commit-range branch dir1 dir2 ... dirN\n";
+ echo "Usage: branch dir1 dir2 ... dirN\n";
exit(1);
}
$dirs = $_SERVER['argv'];
array_shift($dirs);
-$range = array_shift($dirs);
$branch = 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 (!`git diff --name-only $range -- $dir`) {
+ if (!`git diff --name-only $branch...HEAD -- $dir`) {
continue;
}
echo "$dir\n";
diff --git a/.travis.yml b/.travis.yml
index 4718a1090ac7b..778d0e9c04db2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,11 @@ env:
matrix:
include:
+ # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version
- php: hhvm
+ sudo: required
+ dist: trusty
+ group: edge
- php: 5.3
- php: 5.4
- php: 5.5
@@ -35,12 +39,13 @@ cache:
services: mongodb
before_install:
+ - stty cols 120
- PHP=$TRAVIS_PHP_VERSION
# Matrix lines for intermediate PHP versions are skipped for pull requests
- - if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && $PHP != hhvm && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; skip=1; fi
+ - if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; skip=1; fi
# A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi
- - if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
+ - if [[ ! $PHP = hhvm* ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
- if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
- if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
@@ -49,18 +54,17 @@ before_install:
- if [[ ! $skip && $PHP = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.2 && echo apc.enable_cli = 1 >> $INI_FILE); fi
- if [[ ! $deps && $PHP = 5.* ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi
- if [[ ! $skip && $PHP = 5.* ]]; then pecl install -f memcached-2.1.0; fi
- - if [[ ! $skip && $PHP != hhvm ]]; then echo extension = ldap.so >> $INI_FILE; fi
- - if [[ ! $skip && $PHP != hhvm ]]; then phpenv config-rm xdebug.ini; fi
+ - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = ldap.so >> $INI_FILE; fi
+ - if [[ ! $skip && ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini; fi
- if [[ ! $skip ]]; then composer self-update --stable; fi
- - if [[ ! $skip ]]; then cp .composer/* ~/.composer/; composer global install; fi
+ - if [[ ! $skip ]]; then cp .composer/* ~/.composer/; fi
- if [[ ! $skip ]]; then ./phpunit install; fi
- - if [[ ! $skip && $deps ]]; then composer global remove hirak/prestissimo; fi
- if [[ ! $skip ]]; then export PHPUNIT=$(readlink -f ./phpunit); fi
install:
- 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 php .travis.php $TRAVIS_COMMIT_RANGE $TRAVIS_BRANCH $COMPONENTS; fi
+ - if [[ ! $skip && $deps ]]; then php .travis.php $TRAVIS_BRANCH $COMPONENTS; 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
@@ -69,12 +73,13 @@ install:
- 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 [[ ! $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
- - if [[ ! $deps ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi
- - if [[ ! $deps ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
+ - if [[ ! $deps && ! $PHP = hhvm* ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi
+ - if [[ ! $deps && ! $PHP = hhvm* ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
+ - if [[ ! $deps && $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data; fi
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
- if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY; fi
- if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi
diff --git a/CHANGELOG-2.3.md b/CHANGELOG-2.3.md
index d0ca6221aca02..2758f011f3cfd 100644
--- a/CHANGELOG-2.3.md
+++ b/CHANGELOG-2.3.md
@@ -7,6 +7,27 @@ in 2.3 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.3.0...v2.3.1
+* 2.3.42 (2016-05-30)
+
+ * bug #18908 [DependencyInjection] force enabling the external XML entity loaders (xabbuh)
+ * bug #18893 [DependencyInjection] Skip deep reference check for 'service_container' (RobertMe)
+ * bug #18812 Catch \Throwable (fprochazka)
+ * bug #18821 [Form] Removed UTC specification with timestamp (francisbesset)
+ * bug #18861 Fix for #18843 (inso)
+ * bug #18907 [Routing] Fix the annotation loader taking a class constant as a beginning of a class name (jakzal, nicolas-grekas)
+ * bug #18864 [Console][DX] Fixed ambiguous error message when using a duplicate option shortcut (peterrehm)
+ * bug #18844 [Yaml] fix exception contexts (xabbuh)
+ * bug #18840 [Yaml] properly handle unindented collections (xabbuh)
+ * bug #18839 People - person singularization (Keeo)
+ * bug #18828 [Yaml] chomp newlines only at the end of YAML documents (xabbuh)
+ * bug #18635 [Console] Prevent fatal error when calling Command::getHelper without helperSet (chalasr)
+ * bug #18761 [Form] Modified iterator_to_array's 2nd parameter to false in ViolationMapper (issei-m)
+
+* 2.3.41 (2016-05-09)
+
+ * security #18733 limited the maximum length of a submitted username (fabpot)
+ * bug #18709 [DependencyInjection] top-level anonymous services must be public (xabbuh)
+
* 2.3.40 (2016-04-29)
* bug #18246 [DependencyInjection] fix ambiguous services schema (backbone87)
diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md
index 89ee3b549f479..cfe286f2a4caf 100644
--- a/CHANGELOG-2.7.md
+++ b/CHANGELOG-2.7.md
@@ -7,6 +7,14 @@ in 2.7 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1
+* 2.7.13 (2016-05-09)
+
+ * security #18733 limited the maximum length of a submitted username (fabpot)
+ * bug #18730 [FrameworkBundle] prevent calling get() for service_container service (xabbuh)
+ * bug #18709 [DependencyInjection] top-level anonymous services must be public (xabbuh)
+ * bug #18692 add @Event annotation for KernelEvents (Haehnchen)
+ * bug #18246 [DependencyInjection] fix ambiguous services schema (backbone87)
+
* 2.7.12 (2016-04-29)
* bug #18180 [Form] fixed BC break with pre selection of choices with `ChoiceType` and its children (HeahDude)
diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md
index 19d984b3f5b1d..52ff682833743 100644
--- a/CHANGELOG-2.8.md
+++ b/CHANGELOG-2.8.md
@@ -7,6 +7,35 @@ in 2.8 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.8.0...v2.8.1
+* 2.8.7 (2016-06-06)
+
+ * bug #18908 [DependencyInjection] force enabling the external XML entity loaders (xabbuh)
+ * bug #18893 [DependencyInjection] Skip deep reference check for 'service_container' (RobertMe)
+ * bug #18812 Catch \Throwable (fprochazka)
+ * bug #18821 [Form] Removed UTC specification with timestamp (francisbesset)
+ * bug #18861 Fix for #18843 (inso)
+ * bug #18889 [Console] SymfonyStyle: Fix alignment/prefixing of multi-line comments (chalasr)
+ * bug #18907 [Routing] Fix the annotation loader taking a class constant as a beginning of a class name (jakzal, nicolas-grekas)
+ * bug #18879 [Console] SymfonyStyle: Align multi-line/very-long-line blocks (chalasr)
+ * bug #18864 [Console][DX] Fixed ambiguous error message when using a duplicate option shortcut (peterrehm)
+ * bug #18883 Fix js comment in profiler (linnaea)
+ * bug #18844 [Yaml] fix exception contexts (xabbuh)
+ * bug #18840 [Yaml] properly handle unindented collections (xabbuh)
+ * bug #18765 Catch \Throwable (fprochazka)
+ * bug #18813 Catch \Throwable (fprochazka)
+ * bug #18839 People - person singularization (Keeo)
+ * bug #18828 [Yaml] chomp newlines only at the end of YAML documents (xabbuh)
+ * bug #18814 Fixed server status command when port has been omitted (peterrehm)
+ * bug #18799 Use levenshtein level for better Bundle matching (j0k3r)
+ * bug #18413 [WebProfilerBundle] Fix CORS ajax security issues (romainneutron)
+ * bug #18774 [console][table] adjust width of colspanned cell. (aitboudad)
+ * bug #18507 [BUG] Delete class 'control-group' in bootstrap 3 (Philippe Degeeter)
+ * bug #18747 [Form] Modified iterator_to_array's 2nd parameter to false in ViolationMapper (issei-m)
+ * bug #18635 [Console] Prevent fatal error when calling Command::getHelper without helperSet (chalasr)
+ * bug #18686 [console][table] adjust width of colspanned cell. (aitboudad)
+ * bug #18761 [Form] Modified iterator_to_array's 2nd parameter to false in ViolationMapper (issei-m)
+ * bug #18737 [Debug] Fix fatal error handlers on PHP 7 (nicolas-grekas)
+
* 2.8.6 (2016-05-09)
* security #18736 Fixed issue with blank password with Ldap (csarrazi)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 456aeba37aa74..94711183ff113 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -23,8 +23,8 @@ Symfony is the result of the work of many people who made the code better
- Pascal Borreli (pborreli)
- Joseph Bielawski (stloyd)
- Wouter De Jong (wouterj)
- - Karma Dordrak (drak)
- Romain Neutron (romain)
+ - Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
- Martin Hasoň (hason)
- Jeremy Mikola (jmikola)
@@ -40,9 +40,9 @@ Symfony is the result of the work of many people who made the code better
- Alexandre Salomé (alexandresalome)
- William Durand (couac)
- ornicar
+ - Jules Pietri (heah)
- stealth35 (stealth35)
- Alexander Mols (asm89)
- - Jules Pietri (heah)
- Francis Besset (francisbesset)
- Bulat Shakirzyanov (avalanche123)
- Saša Stamenković (umpirsky)
@@ -53,11 +53,11 @@ Symfony is the result of the work of many people who made the code better
- Bilal Amarni (bamarni)
- Florin Patan (florinpatan)
- Kevin Bond (kbond)
+ - Peter Rehm (rpet)
- Gábor Egyed (1ed)
- Michel Weimerskirch (mweimerskirch)
- Eric Clemmons (ericclemmons)
- Andrej Hudec (pulzarraider)
- - Peter Rehm (rpet)
- Christian Raue
- Matthias Pigulla (mpdude)
- Deni
@@ -67,6 +67,7 @@ Symfony is the result of the work of many people who made the code better
- Iltar van der Berg (kjarli)
- Ener-Getick (energetick)
- Douglas Greenshields (shieldo)
+ - Charles Sarrazin (csarrazi)
- Lee McDermott
- Brandon Turner
- Luis Cordova (cordoval)
@@ -74,7 +75,6 @@ Symfony is the result of the work of many people who made the code better
- Pierre du Plessis (pierredup)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- - Charles Sarrazin (csarrazi)
- John Wards (johnwards)
- Toni Uebernickel (havvg)
- Fran Moreno (franmomu)
@@ -89,6 +89,7 @@ Symfony is the result of the work of many people who made the code better
- Alexander M. Turek (derrabus)
- Dariusz Ruminski
- marc.weistroff
+ - Issei Murasawa (issei_m)
- lenar
- Włodzimierz Gajda (gajdaw)
- Alexander Schwenn (xelaris)
@@ -97,13 +98,12 @@ Symfony is the result of the work of many people who made the code better
- Colin Frei
- Adrien Brault (adrienbrault)
- Joshua Thijssen
- - Issei Murasawa (issei_m)
+ - Baptiste Clavié (talus)
- Peter Kokot (maastermedia)
- excelwebzone
- Jacob Dreesen (jdreesen)
- Jérémy DERUSSÉ (jderusse)
- Vladimir Reznichenko (kalessil)
- - Baptiste Clavié (talus)
- Fabien Pennequin (fabienpennequin)
- Gordon Franke (gimler)
- David Buchmann (dbu)
@@ -121,6 +121,7 @@ Symfony is the result of the work of many people who made the code better
- Evgeniy (ewgraf)
- Guilherme Blanco (guilhermeblanco)
- Pablo Godel (pgodel)
+ - Titouan Galopin (tgalopin)
- Jérémie Augustin (jaugustin)
- Sebastiaan Stok (sstok)
- Tugdual Saunier (tucksaun)
@@ -132,6 +133,7 @@ Symfony is the result of the work of many people who made the code better
- Richard Shank (iampersistent)
- Thomas Rabaix (rande)
- Vincent AUBERT (vincent)
+ - Rouven Weßling (realityking)
- Mikael Pajunen
- Clemens Tolboom
- Helmer Aaviksoo
@@ -141,9 +143,7 @@ Symfony is the result of the work of many people who made the code better
- Michał Pipa (michal.pipa)
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
- - Titouan Galopin (tgalopin)
- Artur Kotyrba
- - Rouven Weßling (realityking)
- Warnar Boekkooi (boekkooi)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
@@ -211,6 +211,7 @@ Symfony is the result of the work of many people who made the code better
- Kristen Gilden (kgilden)
- Dawid Nowak
- Pierre-Yves LEBECQ (pylebecq)
+ - Daniel Espendiller
- Jakub Kucharovic (jkucharovic)
- Eugene Leonovich (rybakit)
- Filippo Tessarotto
@@ -292,6 +293,7 @@ Symfony is the result of the work of many people who made the code better
- Inal DJAFAR (inalgnu)
- Christian Gärtner (dagardner)
- Tomasz Kowalczyk (thunderer)
+ - Christian Schmidt
- François-Xavier de Guillebon (de-gui_f)
- Damien Alexandre (damienalexandre)
- Felix Labrecque
@@ -308,6 +310,7 @@ Symfony is the result of the work of many people who made the code better
- Philipp Kräutli (pkraeutli)
- Kirill chEbba Chebunin (chebba)
- Greg Thornton (xdissent)
+ - Robin Chalas (chalas_r)
- Costin Bereveanu (schniper)
- Loïc Chardonnet (gnusat)
- Marek Kalnik (marekkalnik)
@@ -318,12 +321,14 @@ Symfony is the result of the work of many people who made the code better
- Pavel Volokitin (pvolok)
- Endre Fejes
- Tobias Naumann (tna)
+ - Daniel Beyer
- Shein Alexey
- Baptiste Lafontaine
- Joe Lencioni
- Daniel Tschinder
- Kai
- Lee Rowlands
+ - Krzysztof Piasecki (krzysztek)
- Maximilian Reichel (phramz)
- Loick Piera (pyrech)
- Karoly Negyesi (chx)
@@ -363,7 +368,6 @@ Symfony is the result of the work of many people who made the code better
- EdgarPE
- Florian Pfitzer (marmelatze)
- Asier Illarramendi (doup)
- - Christian Schmidt
- Chris Sedlmayr (catchamonkey)
- Seb Koelen
- Christoph Mewes (xrstf)
@@ -381,6 +385,7 @@ Symfony is the result of the work of many people who made the code better
- Mathieu Lemoine
- franek (franek)
- Christian Wahler
+ - Mathieu Lemoine
- Gintautas Miselis
- Zander Baldwin
- Adam Harvey
@@ -418,7 +423,6 @@ Symfony is the result of the work of many people who made the code better
- Anthony Ferrara
- Ioan Negulescu
- Jakub Škvára (jskvara)
- - Daniel Beyer
- Andrew Udvare (audvare)
- alexpods
- Tristan Darricau (nicofuma)
@@ -436,6 +440,7 @@ Symfony is the result of the work of many people who made the code better
- Benjamin Leveque (benji07)
- Nate (frickenate)
- jhonnyL
+ - Jhonny Lidfors (jhonne)
- sasezaki
- Dawid Pakuła (zulusx)
- Florian Rey (nervo)
@@ -446,6 +451,7 @@ Symfony is the result of the work of many people who made the code better
- Denis Gorbachev (starfall)
- Peter van Dommelen
- Tim van Densen
+ - Martin Morávek (keeo)
- Steven Surowiec
- Kevin Saliou (kbsali)
- NothingWeAre
@@ -460,7 +466,6 @@ Symfony is the result of the work of many people who made the code better
- Ziumin
- Jeremy Benoist
- Lenar Lõhmus
- - Krzysztof Piasecki (krzysztek)
- Benjamin Laugueux (yzalis)
- Zach Badgett (zachbadgett)
- Aurélien Fredouelle
@@ -499,6 +504,7 @@ Symfony is the result of the work of many people who made the code better
- Javier López (loalf)
- Reinier Kip
- Dustin Dobervich (dustin10)
+ - dantleech
- Anne-Sophie Bachelard (annesophie)
- Sebastian Marek (proofek)
- Erkhembayar Gantulga (erheme318)
@@ -561,6 +567,7 @@ Symfony is the result of the work of many people who made the code better
- Peter Ward
- Dominik Ritter (dritter)
- Sebastian Grodzicki (sgrodzicki)
+ - SpacePossum
- Martin Hujer (martinhujer)
- Pascal Helfenstein
- Baldur Rensch (brensch)
@@ -611,7 +618,7 @@ Symfony is the result of the work of many people who made the code better
- Adrien Lucas (adrienlucas)
- James Michael DuPont
- Tom Klingenberg
- - Jhonny Lidfors (jhonne)
+ - Filip Procházka (fprochazka)
- Christopher Hall (mythmakr)
- Paul Kamer (pkamer)
- Rafał Wrzeszcz (rafalwrzeszcz)
@@ -628,6 +635,7 @@ Symfony is the result of the work of many people who made the code better
- Alaattin Kahramanlar (alaattin)
- Maksim Kotlyar (makasim)
- Neil Ferreira
+ - Nathanael Noblet (gnat)
- Dmitry Parnas (parnas)
- Théo FIDRY (theofidry)
- Paul LE CORRE
@@ -744,7 +752,6 @@ Symfony is the result of the work of many people who made the code better
- Guillaume Royer
- Artem (digi)
- boite
- - dantleech
- Vadim Tyukov (vatson)
- Sortex
- chispita
@@ -850,6 +857,7 @@ Symfony is the result of the work of many people who made the code better
- Christian Sciberras
- Anton Bakai
- Clement Herreman (clemherreman)
+ - Dan Ionut Dumitriu (danionut90)
- Nyro (nyro)
- Marco
- Marc Torres
@@ -869,7 +877,6 @@ Symfony is the result of the work of many people who made the code better
- ConneXNL
- Aharon Perkel
- Abdul.Mohsen B. A. A
- - SpacePossum
- Benoît Burnichon
- Remi Collet
- pthompson
@@ -904,7 +911,6 @@ Symfony is the result of the work of many people who made the code better
- Albin Kerouaton
- Sébastien HOUZÉ
- Jingyu Wang
- - Daniel Espendiller
- steveYeah
- Samy Dindane (dinduks)
- Keri Henare (kerihenare)
@@ -945,6 +951,7 @@ Symfony is the result of the work of many people who made the code better
- Tadcka
- Beth Binkovitz
- Romain Geissler
+ - Oliver Hoff
- Tomaz Ahlin
- Benjamin Cremer (bcremer)
- Marcus Stöhr (dafish)
@@ -1058,6 +1065,7 @@ Symfony is the result of the work of many people who made the code better
- stloyd
- Chris Tickner
- Andrew Coulton
+ - Jeremy Benoist
- Michal Gebauer
- Gleb Sidora
- David Stone
@@ -1107,7 +1115,6 @@ Symfony is the result of the work of many people who made the code better
- Simon Sargeant
- efeen
- Michał Dąbrowski (defrag)
- - Nathanael Noblet (gnat)
- Simone Fumagalli (hpatoio)
- Brian Graham (incognito)
- Kevin Vergauwen (innocenzo)
@@ -1213,8 +1220,10 @@ Symfony is the result of the work of many people who made the code better
- Alan Chen
- Maerlyn
- Even André Fiskvik
+ - Erik van Wingerden
- Dane Powell
- Gerrit Drost
+ - Linnaea Von Lavia
- Lenar Lõhmus
- Cristian Gonzalez
- AlberT
@@ -1270,6 +1279,7 @@ Symfony is the result of the work of many people who made the code better
- Joseph Deray
- Damian Sromek
- Ben
+ - dasmfm
- Arnaud Buathier (arnapou)
- chesteroni (chesteroni)
- Mauricio Lopez (diaspar)
@@ -1302,6 +1312,7 @@ Symfony is the result of the work of many people who made the code better
- znerol
- Christian Eikermann
- Antonio Angelino
+ - Shawn Iwinski
- Vladimir Sazhin
- lol768
- jamogon
@@ -1356,7 +1367,6 @@ Symfony is the result of the work of many people who made the code better
- Norman Soetbeer
- zorn
- Benjamin Long
- - Robin Chalas
- Matt Janssen
- Peter Gribanov
- kwiateusz
@@ -1441,6 +1451,7 @@ Symfony is the result of the work of many people who made the code better
- ollie harridge (ollietb)
- Paul Andrieux (paulandrieux)
- Paweł Szczepanek (pauluz)
+ - Philippe Degeeter (pdegeeter)
- Christian López Espínola (penyaskito)
- Petr Jaroš (petajaros)
- Philipp Hoffmann (philipphoffmann)
diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md
index 35823d8aaf234..08796bd419d29 100644
--- a/UPGRADE-3.0.md
+++ b/UPGRADE-3.0.md
@@ -365,8 +365,11 @@ UPGRADE FROM 2.x to 3.0
```
- * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`,
- `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed.
+ * The `max_length` option was removed. Use the `attr` option instead by setting it to
+ an `array` with a `maxlength` key.
+
+ * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`,
+ `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed.
* The `choice_list` option of `ChoiceType` was removed.
@@ -1037,6 +1040,39 @@ UPGRADE FROM 2.x to 3.0
}
```
+ * The `AbstractVoter::isGranted()` method has been replaced by `Voter::voteOnAttribute()`.
+
+ Before:
+
+ ```php
+ class MyVoter extends AbstractVoter
+ {
+ protected function isGranted($attribute, $object, $user = null)
+ {
+ return 'EDIT' === $attribute && $user === $object->getAuthor();
+ }
+
+ // ...
+ }
+ ```
+
+ After:
+
+ ```php
+ class MyVoter extends Voter
+ {
+ protected function voteOnAttribute($attribute, $object, TokenInterface $token)
+ {
+ return 'EDIT' === $attribute && $token->getUser() === $object->getAuthor();
+ }
+
+ // ...
+ }
+ ```
+
+ * The `supportsAttribute()` and `supportsClass()` methods of the `AuthenticatedVoter`, `ExpressionVoter`,
+ and `RoleVoter` classes have been removed.
+
* The `intention` option was renamed to `csrf_token_id` for all the authentication listeners.
* The `csrf_provider` option was renamed to `csrf_token_generator` for all the authentication listeners.
@@ -1604,8 +1640,7 @@ UPGRADE FROM 2.x to 3.0
### WebProfiler
- * The `profiler:import` and `profiler:export` commands have been deprecated and
- will be removed in 3.0.
+ * The `profiler:import` and `profiler:export` commands have been removed.
* All the profiler storages different than `FileProfilerStorage` have been
removed. The removed classes are:
diff --git a/appveyor.yml b/appveyor.yml
index 4a64d1494c765..c75b19aea94a9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -18,7 +18,7 @@ init:
install:
- IF EXIST c:\php (SET PHP=0) ELSE (mkdir c:\php)
- cd c:\php
- - IF %PHP%==1 appveyor DownloadFile https://curl.haxx.se/ca/cacert.pem
+ - IF %PHP%==1 appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem
- IF %PHP%==1 appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-5.3.11-nts-Win32-VC9-x86.zip
- IF %PHP%==1 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y >nul
- IF %PHP%==1 appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/ICU-51.2-dlls.zip
@@ -50,12 +50,11 @@ install:
- IF %PHP%==1 echo extension=php_ldap.dll >> php.ini-max
- IF %PHP%==1 echo extension=php_curl.dll >> php.ini-max
- IF %PHP%==1 echo curl.cainfo=c:\php\cacert.pem >> php.ini-max
- - IF %PHP%==1 appveyor DownloadFile https://getcomposer.org/download/1.0.2/composer.phar
+ - IF %PHP%==1 appveyor DownloadFile https://getcomposer.org/download/1.0.3/composer.phar
- copy /Y php.ini-max php.ini
- cd c:\projects\symfony
- mkdir %APPDATA%\Composer
- copy /Y .composer\* %APPDATA%\Composer\
- - composer global install --no-progress --ansi
- php phpunit install
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
- composer update --no-progress --ansi
diff --git a/phpunit b/phpunit
index 6d66f7b2b252a..3ab3ca1686042 100755
--- a/phpunit
+++ b/phpunit
@@ -53,6 +53,9 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
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.1@dev\"");
passthru("$COMPOSER install --prefer-dist --no-progress --ansi", $exit);
if ($exit) {
@@ -170,8 +173,11 @@ if (isset($argv[1]) && 'symfony' === $argv[1]) {
unlink($file);
}
- // Fail on any individual component failures but ignore STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409) and STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005) on Windows when APCu is enabled
- if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || (-1073740791 !== $procStatus && -1073741819 !== $procStatus))) {
+ // 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 {
diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
index 1712bd5afee8e..f9333bf683d1a 100644
--- a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
+++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
@@ -67,9 +67,9 @@ public function leave()
* @param string $key
* @param mixed $value
*
- * @throws \LogicException
- *
* @return Scope Current scope
+ *
+ * @throws \LogicException
*/
public function set($key, $value)
{
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
index 0fb3f769b8391..ef2035ab43f04 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
@@ -94,14 +94,12 @@
{% block choice_widget_expanded -%}
{% if '-inline' in label_attr.class|default('') -%}
-
- {%- for child in form %}
- {{- form_widget(child, {
- parent_label_class: label_attr.class|default(''),
- translation_domain: choice_translation_domain,
- }) -}}
- {% endfor -%}
-
+ {%- for child in form %}
+ {{- form_widget(child, {
+ parent_label_class: label_attr.class|default(''),
+ translation_domain: choice_translation_domain,
+ }) -}}
+ {% endfor -%}
{%- else -%}
{%- for child in form %}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
index b6ec558701a14..d7cb9e7d08197 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
@@ -13,6 +13,7 @@
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -32,6 +33,7 @@ protected function configure()
$this
->setDefinition(array(
new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
+ new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
))
->setName('server:status')
->setDescription('Outputs the status of the built-in web server for the given address')
@@ -46,6 +48,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io = new SymfonyStyle($input, $output);
$address = $input->getArgument('address');
+ if (false === strpos($address, ':')) {
+ $address = $address.':'.$input->getOption('port');
+ }
+
// remove an orphaned lock file
if (file_exists($this->getLockFile($address)) && !$this->isServerRunning($address)) {
unlink($this->getLockFile($address));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
index dca8ffc4839ee..4aa00a85dbb17 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
@@ -339,7 +339,7 @@ protected function describeContainerDefinition(Definition $definition, array $op
*/
protected function describeContainerAlias(Alias $alias, array $options = array())
{
- $options['output']->comment(sprintf("This service is an alias for the service
%s\n", (string) $alias));
+ $options['output']->comment(sprintf('This service is an alias for the service
%s', (string) $alias));
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
index 873c736841ba8..374d0eba10ff6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
@@ -142,6 +142,7 @@ private function findAlternative($nonExistentBundleName)
$lev = levenshtein($nonExistentBundleName, $bundleName);
if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) {
$alternative = $bundleName;
+ $shortest = $lev;
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
index 9888ce8fed25a..e916ef86689ff 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
@@ -84,6 +84,9 @@ public function load($resource, $type = null)
} catch (\Exception $e) {
$this->loading = false;
throw $e;
+ } catch (\Throwable $e) {
+ $this->loading = false;
+ throw $e;
}
$this->loading = false;
@@ -92,7 +95,7 @@ public function load($resource, $type = null)
if ($controller = $route->getDefault('_controller')) {
try {
$controller = $this->parser->parse($controller);
- } catch (\Exception $e) {
+ } catch (\InvalidArgumentException $e) {
// unable to optimize unknown notation
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
index 4718c1eb0b238..0fe47b0908d83 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
@@ -59,8 +59,8 @@ public function testBuild()
{
$parser = $this->createParser();
- $this->assertEquals('FooBundle:Default:index', $parser->build('TestBundle\FooBundle\Controller\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
- $this->assertEquals('FooBundle:Sub\Default:index', $parser->build('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
+ $this->assertEquals('FoooooBundle:Default:index', $parser->build('TestBundle\FooBundle\Controller\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
+ $this->assertEquals('FoooooBundle:Sub\Default:index', $parser->build('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
try {
$parser->build('TestBundle\FooBundle\Controller\DefaultController::index');
@@ -132,8 +132,9 @@ public function testInvalidBundleName($bundleName, $suggestedBundleName)
public function getInvalidBundleNameTests()
{
return array(
- array('FoodBundle:Default:index', 'FooBundle:Default:index'),
- array('CrazyBundle:Default:index', false),
+ 'Alternative will be found using levenshtein' => array('FoodBundle:Default:index', 'FooBundle:Default:index'),
+ 'Alternative will be found using partial match' => array('FabpotFooBund:Default:index', 'FabpotFooBundle:Default:index'),
+ 'Bundle does not exist at all' => array('CrazyBundle:Default:index', false),
);
}
@@ -162,6 +163,7 @@ private function createParser()
$bundles = array(
'SensioFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'),
+ 'FoooooBundle' => $this->getBundle('TestBundle\FooBundle', 'FoooooBundle'),
'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'),
'FabpotFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
index b4dc8ada555b6..00ffa4c1fd162 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
@@ -150,7 +150,7 @@ public function getUndefinedControllers()
{
return array(
array('foo', '\LogicException', 'Unable to parse the controller name "foo".'),
- array('foo::bar', '\InvalidArgumentException', 'Class "foo" does not exist.'),
+ array('oof::bar', '\InvalidArgumentException', 'Class "oof" does not exist.'),
array('stdClass', '\LogicException', 'Unable to parse the controller name "stdClass".'),
array(
'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar',
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_1.txt
index c3b9987ec27f5..91ed6790f03b7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_1.txt
@@ -1 +1,3 @@
-// This service is an alias for the service [32mservice_1[39m
\ No newline at end of file
+
+ // This service is an alias for the service [32mservice_1[39m
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_2.txt
index b53b090b5f3c9..1ebffe38ac58a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_2.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_2.txt
@@ -1 +1,3 @@
-// This service is an alias for the service [32mservice_2[39m
\ No newline at end of file
+
+ // This service is an alias for the service [32mservice_2[39m
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
index ca9e7f994c090..cf7f3c5769bf2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
@@ -182,9 +182,9 @@ protected function parseTokens($tokens, MessageCatalogue $catalog)
/**
* @param string $file
*
- * @throws \InvalidArgumentException
- *
* @return bool
+ *
+ * @throws \InvalidArgumentException
*/
protected function canBeExtracted($file)
{
diff --git a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php
index fc62ef059daaf..976086920e07b 100644
--- a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php
+++ b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php
@@ -95,9 +95,9 @@ public function getName()
*
* @param string $url The URL that has to be absolute
*
- * @throws \RuntimeException
- *
* @return string The absolute URL
+ *
+ * @throws \RuntimeException
*/
private function ensureUrlIsAbsolute($url)
{
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
index 408e5c6bdcbf3..03617dfa957b3 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
@@ -82,6 +82,20 @@
requestStack = [],
+ extractHeaders = function(xhr, stackElement) {
+ /* Here we avoid to call xhr.getResponseHeader in order to */
+ /* prevent polluting the console with CORS security errors */
+ var allHeaders = xhr.getAllResponseHeaders();
+ var ret;
+
+ if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) {
+ stackElement.profile = ret[1];
+ }
+ if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) {
+ stackElement.profilerUrl = ret[1];
+ }
+ },
+
renderAjaxRequests = function() {
var requestCounter = document.querySelectorAll('.sf-toolbar-ajax-requests');
if (!requestCounter.length) {
@@ -241,8 +255,8 @@
stackElement.duration = new Date() - stackElement.start;
stackElement.loading = false;
stackElement.error = self.status < 200 || self.status >= 400;
- stackElement.profile = self.getResponseHeader("X-Debug-Token");
- stackElement.profilerUrl = self.getResponseHeader("X-Debug-Token-Link");
+
+ extractHeaders(self, stackElement);
Sfjs.renderAjaxRequests();
}
diff --git a/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php b/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php
new file mode 100644
index 0000000000000..77958ce2ca0cc
--- /dev/null
+++ b/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Asset\Tests\VersionStrategy;
+
+use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
+
+class StaticVersionStrategyTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetVersion()
+ {
+ $version = 'v1';
+ $path = 'test-path';
+ $staticVersionStrategy = new StaticVersionStrategy($version);
+ $this->assertEquals($version, $staticVersionStrategy->getVersion($path));
+ }
+
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testApplyVersion($path, $version, $format)
+ {
+ $staticVersionStrategy = new StaticVersionStrategy($version, $format);
+ $formatted = sprintf($format ?: '%s?%s', $path, $version);
+ $this->assertEquals($formatted, $staticVersionStrategy->applyVersion($path));
+ }
+
+ public function getConfigs()
+ {
+ return array(
+ array('test-path', 'v1', null),
+ array('test-path', 'v2', '%s?test%s'),
+ );
+ }
+}
diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json
index 2072c95e6e4e2..1deb892a5a5b1 100644
--- a/src/Symfony/Component/BrowserKit/composer.json
+++ b/src/Symfony/Component/BrowserKit/composer.json
@@ -17,7 +17,7 @@
],
"require": {
"php": ">=5.3.9",
- "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0"
+ "symfony/dom-crawler": "~2.1|~3.0.0"
},
"require-dev": {
"symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0",
diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php
index 88ec070f17a80..2b19b52584bdd 100644
--- a/src/Symfony/Component/Config/Loader/FileLoader.php
+++ b/src/Symfony/Component/Config/Loader/FileLoader.php
@@ -113,6 +113,9 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe
} catch (\Exception $e) {
unset(self::$loading[$resource]);
throw $e;
+ } catch (\Throwable $e) {
+ unset(self::$loading[$resource]);
+ throw $e;
}
unset(self::$loading[$resource]);
diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php
index 6dddc8def2be5..6acbe2198fb14 100644
--- a/src/Symfony/Component/Console/Command/Command.php
+++ b/src/Symfony/Component/Console/Command/Command.php
@@ -307,14 +307,14 @@ public function mergeApplicationDefinition($mergeArgs = true)
return;
}
+ $this->definition->addOptions($this->application->getDefinition()->getOptions());
+
if ($mergeArgs) {
$currentArguments = $this->definition->getArguments();
$this->definition->setArguments($this->application->getDefinition()->getArguments());
$this->definition->addArguments($currentArguments);
}
- $this->definition->addOptions($this->application->getDefinition()->getOptions());
-
$this->applicationDefinitionMerged = true;
if ($mergeArgs) {
$this->applicationDefinitionMergedWithArgs = true;
@@ -608,10 +608,15 @@ public function getUsages()
*
* @return mixed The helper value
*
+ * @throws LogicException if no HelperSet is defined
* @throws InvalidArgumentException if the helper is not defined
*/
public function getHelper($name)
{
+ if (null === $this->helperSet) {
+ throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
+ }
+
return $this->helperSet->get($name);
}
diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php
index dc038e4707c16..13e4c3cf6b519 100644
--- a/src/Symfony/Component/Console/Helper/Table.php
+++ b/src/Symfony/Component/Console/Helper/Table.php
@@ -307,7 +307,7 @@ private function renderRowSeparator()
*/
private function renderColumnSeparator()
{
- $this->output->write(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
+ return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
}
/**
@@ -324,12 +324,12 @@ private function renderRow(array $row, $cellFormat)
return;
}
- $this->renderColumnSeparator();
+ $rowContent = $this->renderColumnSeparator();
foreach ($this->getRowColumns($row) as $column) {
- $this->renderCell($row, $column, $cellFormat);
- $this->renderColumnSeparator();
+ $rowContent .= $this->renderCell($row, $column, $cellFormat);
+ $rowContent .= $this->renderColumnSeparator();
}
- $this->output->writeln('');
+ $this->output->writeln($rowContent);
}
/**
@@ -358,12 +358,13 @@ private function renderCell(array $row, $column, $cellFormat)
$style = $this->getColumnStyle($column);
if ($cell instanceof TableSeparator) {
- $this->output->write(sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width)));
- } else {
- $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
- $content = sprintf($style->getCellRowContentFormat(), $cell);
- $this->output->write(sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())));
+ return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
}
+
+ $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
+ $content = sprintf($style->getCellRowContentFormat(), $cell);
+
+ return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
}
/**
@@ -569,6 +570,18 @@ private function calculateColumnsWidth($rows)
continue;
}
+ foreach ($row as $i => $cell) {
+ if ($cell instanceof TableCell) {
+ $textLength = strlen($cell);
+ if ($textLength > 0) {
+ $contentColumns = str_split($cell, ceil($textLength / $cell->getColspan()));
+ foreach ($contentColumns as $position => $content) {
+ $row[$i + $position] = $content;
+ }
+ }
+ }
+ }
+
$lengths[] = $this->getCellWidth($row, $column);
}
@@ -599,10 +612,6 @@ private function getCellWidth(array $row, $column)
if (isset($row[$column])) {
$cell = $row[$column];
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
- if ($cell instanceof TableCell && $cell->getColspan() > 1) {
- // we assume that cell value will be across more than one column.
- $cellWidth = $cellWidth / $cell->getColspan();
- }
return $cellWidth;
}
diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php
index 098966286eeb5..9e6b74810d282 100644
--- a/src/Symfony/Component/Console/Output/StreamOutput.php
+++ b/src/Symfony/Component/Console/Output/StreamOutput.php
@@ -72,7 +72,7 @@ public function getStream()
*/
protected function doWrite($message, $newline)
{
- if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
+ if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
// should never happen
throw new RuntimeException('Unable to write output.');
}
diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php
index 6086918ac7840..53a7951e016d7 100644
--- a/src/Symfony/Component/Console/Style/SymfonyStyle.php
+++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php
@@ -68,23 +68,36 @@ public function block($messages, $type = null, $style = null, $prefix = ' ', $pa
{
$this->autoPrependBlock();
$messages = is_array($messages) ? array_values($messages) : array($messages);
+ $indentLength = 0;
$lines = array();
- // add type
if (null !== $type) {
- $messages[0] = sprintf('[%s] %s', $type, $messages[0]);
+ $typePrefix = sprintf('[%s] ', $type);
+ $indentLength = strlen($typePrefix);
+ $lineIndentation = str_repeat(' ', $indentLength);
}
// wrap and add newlines for each element
foreach ($messages as $key => $message) {
$message = OutputFormatter::escape($message);
- $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix), PHP_EOL, true)));
+ $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix) - $indentLength, PHP_EOL, true)));
+
+ // prefix each line with a number of spaces equivalent to the type length
+ if (null !== $type) {
+ foreach ($lines as &$line) {
+ $line = $lineIndentation === substr($line, 0, $indentLength) ? $line : $lineIndentation.$line;
+ }
+ }
if (count($messages) > 1 && $key < count($messages) - 1) {
$lines[] = '';
}
}
+ if (null !== $type) {
+ $lines[0] = substr_replace($lines[0], $typePrefix, 0, $indentLength);
+ }
+
if ($padding && $this->isDecorated()) {
array_unshift($lines, '');
$lines[] = '';
@@ -157,16 +170,18 @@ public function text($message)
}
/**
- * {@inheritdoc}
+ * Formats a command comment.
+ *
+ * @param string|array $message
*/
public function comment($message)
{
- $this->autoPrependText();
-
$messages = is_array($message) ? array_values($message) : array($message);
- foreach ($messages as $message) {
- $this->writeln(sprintf(' // %s', $message));
+ foreach ($messages as &$message) {
+ $message = $this->getFormatter()->format($message);
}
+
+ $this->block($messages, null, null, ' // ');
}
/**
diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php
index c5e16088b25b8..927fa0bd820e8 100644
--- a/src/Symfony/Component/Console/Tests/ApplicationTest.php
+++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php
@@ -734,6 +734,33 @@ public function testRunReturnsExitCodeOneForExceptionCodeZero()
$this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
}
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage An option with shortcut "e" already exists.
+ */
+ public function testAddingOptionWithDuplicateShortcut()
+ {
+ $dispatcher = new EventDispatcher();
+ $application = new Application();
+ $application->setAutoExit(false);
+ $application->setCatchExceptions(false);
+ $application->setDispatcher($dispatcher);
+
+ $application->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'Environment'));
+
+ $application
+ ->register('foo')
+ ->setAliases(array('f'))
+ ->setDefinition(array(new InputOption('survey', 'e', InputOption::VALUE_REQUIRED, 'My option with a shortcut.')))
+ ->setCode(function (InputInterface $input, OutputInterface $output) {})
+ ;
+
+ $input = new ArrayInput(array('command' => 'foo'));
+ $output = new NullOutput();
+
+ $application->run($input, $output);
+ }
+
/**
* @expectedException \LogicException
* @dataProvider getAddingAlreadySetDefinitionElementData
diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php
index a5af27ca344d1..e8836d8c61439 100644
--- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php
+++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php
@@ -173,6 +173,16 @@ public function testGetHelper()
$this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper');
}
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cannot retrieve helper "formatter" because there is no HelperSet defined.
+ */
+ public function testGetHelperWithoutHelperSet()
+ {
+ $command = new \TestCommand();
+ $command->getHelper('formatter');
+ }
+
public function testMergeApplicationDefinition()
{
$application1 = new Application();
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php
new file mode 100644
index 0000000000000..4120df9cb6b64
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php
@@ -0,0 +1,17 @@
+block(
+ 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum',
+ 'CUSTOM',
+ 'fg=white;bg=green',
+ 'X ',
+ true
+ );
+};
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php
new file mode 100644
index 0000000000000..a2781ddbeafa4
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php
@@ -0,0 +1,13 @@
+comment(
+ 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
+ );
+};
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php
new file mode 100644
index 0000000000000..6420730fd64ad
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php
@@ -0,0 +1,11 @@
+block(array('Custom block', 'Second custom block line'), 'CUSTOM', 'fg=white;bg=green', 'X ', true);
+};
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt
new file mode 100644
index 0000000000000..385c6a283c84d
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt
@@ -0,0 +1,7 @@
+
+X [CUSTOM] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
+X dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+X commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
+X nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+X anim id est laborum
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt
new file mode 100644
index 0000000000000..9983af832aa7d
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt
@@ -0,0 +1,6 @@
+
+ // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
+ // aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+ // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
+ // sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt
index 738eb9e606010..be4a2db605795 100644
--- a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt
@@ -11,5 +11,8 @@ Lorem ipsum dolor sit amet
consectetur adipiscing elit
Lorem ipsum dolor sit amet
- // Lorem ipsum dolor sit amet
- // consectetur adipiscing elit
+
+ // Lorem ipsum dolor sit amet
+ //
+ // consectetur adipiscing elit
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt
new file mode 100644
index 0000000000000..069c0d5119f7b
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt
@@ -0,0 +1,5 @@
+
+X [CUSTOM] Custom block
+X
+X Second custom block line
+
diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php
index d917d69591aa8..9ecb381a80090 100644
--- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php
+++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php
@@ -269,21 +269,27 @@ public function testRenderProvider()
'9971-5-0210-0',
new TableCell("A Tale of \nTwo Cities", array('colspan' => 2)),
),
+ new TableSeparator(),
+ array(
+ new TableCell('Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil!', array('colspan' => 3)),
+ ),
),
'default',
<<
isRecursive = false;
+ throw $e;
+ } catch (\Throwable $e) {
+ $this->isRecursive = false;
+
throw $e;
}
}
@@ -539,7 +543,7 @@ public function handleException($exception, array $error = null)
}
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
- if ($this->loggedErrors & $type) {
+ if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
$e = array(
'type' => $type,
'file' => $exception->getFile(),
@@ -566,9 +570,9 @@ public function handleException($exception, array $error = null)
} else {
$message = 'Uncaught Exception: '.$exception->getMessage();
}
- if ($this->loggedErrors & $e['type']) {
- $this->loggers[$e['type']][0]->log($this->loggers[$e['type']][1], $message, $e);
- }
+ }
+ if ($this->loggedErrors & $type) {
+ $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
}
if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
foreach ($this->getFatalErrorHandlers() as $handler) {
@@ -625,6 +629,8 @@ public static function handleFatalError(array $error = null)
}
} catch (\Exception $exception) {
// Handled below
+ } catch (\Throwable $exception) {
+ // Handled below
}
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
diff --git a/src/Symfony/Component/Debug/Exception/FatalThrowableError.php b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php
index 6ff5ecdaffed0..34f43b17b13b4 100644
--- a/src/Symfony/Component/Debug/Exception/FatalThrowableError.php
+++ b/src/Symfony/Component/Debug/Exception/FatalThrowableError.php
@@ -27,7 +27,7 @@ public function __construct(\Throwable $e)
$message = 'Type error: '.$e->getMessage();
$severity = E_RECOVERABLE_ERROR;
} else {
- $message = 'Fatal error: '.$e->getMessage();
+ $message = $e->getMessage();
$severity = E_ERROR;
}
diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
index 927009c1a45e8..51c96727873ae 100644
--- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
+++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
@@ -484,6 +484,24 @@ public function testHandleFatalError()
}
}
+ /**
+ * @requires PHP 7
+ */
+ public function testHandleErrorException()
+ {
+ $exception = new \Error("Class 'Foo' not found");
+
+ $handler = new ErrorHandler();
+ $handler->setExceptionHandler(function () use (&$args) {
+ $args = func_get_args();
+ });
+
+ $handler->handleException($exception);
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]);
+ $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
+ }
+
public function testHandleFatalErrorOnHHVM()
{
try {
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
index e4457d4608451..5065ed1880e87 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
@@ -44,8 +44,8 @@ public function process(ContainerBuilder $container)
$this->completeDefinition($id, $definition);
}
}
- } catch (\Error $e) {
} catch (\Exception $e) {
+ } catch (\Throwable $e) {
}
spl_autoload_unregister($throwingAutoloader);
@@ -225,13 +225,16 @@ private function set($type, $id)
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
{
if (isset($this->notGuessableTypes[$typeHint->name])) {
- throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Several services implementing this type have been declared: "%s".', $typeHint->name, $id, implode('", "', $this->types[$typeHint->name])));
- }
+ $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
+ $matchingServices = implode(', ', $this->types[$typeHint->name]);
+
+ throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices));
- $noAvailableDefinitionMessage = sprintf('Unable to autowire argument of type "%s" for the service "%s". This type cannot be instantiated automatically and no service implementing this type is declared.', $typeHint->name, $id);
+ }
if (!$typeHint->isInstantiable()) {
- throw new RuntimeException($noAvailableDefinitionMessage);
+ $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
+ throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface));
}
$argumentId = sprintf('autowired.%s', $typeHint->name);
@@ -244,7 +247,9 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
try {
$this->completeDefinition($argumentId, $argumentDefinition);
} catch (RuntimeException $e) {
- throw new RuntimeException($noAvailableDefinitionMessage, 0, $e);
+ $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
+ $message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface);
+ throw new RuntimeException($message, 0, $e);
}
return new Reference($argumentId);
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
index 51ea1bc2a3130..f8f27408ca2e3 100644
--- a/src/Symfony/Component/DependencyInjection/Container.php
+++ b/src/Symfony/Component/DependencyInjection/Container.php
@@ -320,6 +320,11 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
return;
}
+ throw $e;
+ } catch (\Throwable $e) {
+ unset($this->loading[$id]);
+ unset($this->services[$id]);
+
throw $e;
}
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index b49cb5f6fd2ae..4544f478cd7bb 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -480,6 +480,10 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
return;
}
+ throw $e;
+ } catch (\Throwable $e) {
+ unset($this->loading[$id]);
+
throw $e;
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index c11d15864afbc..9394876731dce 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -1288,7 +1288,7 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
return true;
}
- if ($deep && !isset($visited[$argumentId])) {
+ if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
$visited[$argumentId] = true;
$service = $this->container->getDefinition($argumentId);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
index 6098d9a9131c8..b5badc31fdbcd 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
@@ -103,7 +103,7 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Several services implementing this type have been declared: "c1", "c2".
+ * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (c1, c2, c3).
*/
public function testTypeCollision()
{
@@ -111,6 +111,7 @@ public function testTypeCollision()
$container->register('c1', __NAMESPACE__.'\CollisionA');
$container->register('c2', __NAMESPACE__.'\CollisionB');
+ $container->register('c3', __NAMESPACE__.'\CollisionB');
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
$aDefinition->setAutowired(true);
@@ -120,7 +121,7 @@ public function testTypeCollision()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a". Several services implementing this type have been declared: "a1", "a2".
+ * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a". Multiple services exist for this class (a1, a2).
*/
public function testTypeNotGuessable()
{
@@ -137,7 +138,7 @@ public function testTypeNotGuessable()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a". Several services implementing this type have been declared: "a1", "a2".
+ * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a". Multiple services exist for this class (a1, a2).
*/
public function testTypeNotGuessableWithSubclass()
{
@@ -152,6 +153,21 @@ public function testTypeNotGuessableWithSubclass()
$pass->process($container);
}
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
+ * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". No services were found matching this interface and it cannot be auto-registered.
+ */
+ public function testTypeNotGuessableNoServicesFound()
+ {
+ $container = new ContainerBuilder();
+
+ $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
+ $aDefinition->setAutowired(true);
+
+ $pass = new AutowirePass();
+ $pass->process($container);
+ }
+
public function testTypeNotGuessableWithTypeSet()
{
$container = new ContainerBuilder();
@@ -207,21 +223,6 @@ public function testCreateDefinition()
$this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass());
}
- /**
- * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". This type cannot be instantiated automatically and no service implementing this type is declared.
- */
- public function testCreateNonInstanciable()
- {
- $container = new ContainerBuilder();
-
- $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
- $aDefinition->setAutowired(true);
-
- $pass = new AutowirePass();
- $pass->process($container);
- }
-
public function testResolveParameter()
{
$container = new ContainerBuilder();
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
index 6f600166ff1d9..a6b92c53698e9 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -264,4 +264,15 @@ public function testDumpAutowireData()
$this->assertEquals(file_get_contents(self::$fixturesPath.'/php/services24.php'), $dumper->dump());
}
+
+ public function testInlinedDefinitionReferencingServiceContainer()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')->addMethodCall('add', array(new Reference('service_container')))->setPublic(false);
+ $container->register('bar', 'stdClass')->addArgument(new Reference('foo'));
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
+ }
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php
new file mode 100644
index 0000000000000..f6038f390367e
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php
@@ -0,0 +1,62 @@
+services =
+ $this->scopedServices =
+ $this->scopeStacks = array();
+ $this->scopes = array();
+ $this->scopeChildren = array();
+ $this->methodMap = array(
+ 'bar' => 'getBarService',
+ );
+
+ $this->aliases = array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function compile()
+ {
+ throw new LogicException('You cannot compile a dumped frozen container.');
+ }
+
+ /**
+ * Gets the 'bar' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \stdClass A stdClass instance.
+ */
+ protected function getBarService()
+ {
+ $a = new \stdClass();
+ $a->add($this);
+
+ return $this->services['bar'] = new \stdClass($a);
+ }
+}
diff --git a/src/Symfony/Component/EventDispatcher/GenericEvent.php b/src/Symfony/Component/EventDispatcher/GenericEvent.php
index 6458180a5aac3..03cbcfe33414e 100644
--- a/src/Symfony/Component/EventDispatcher/GenericEvent.php
+++ b/src/Symfony/Component/EventDispatcher/GenericEvent.php
@@ -61,9 +61,9 @@ public function getSubject()
*
* @param string $key Key.
*
- * @throws \InvalidArgumentException If key is not found.
- *
* @return mixed Contents of array key.
+ *
+ * @throws \InvalidArgumentException If key is not found.
*/
public function getArgument($key)
{
@@ -130,9 +130,9 @@ public function hasArgument($key)
*
* @param string $key Array key.
*
- * @throws \InvalidArgumentException If key does not exist in $this->args.
- *
* @return mixed
+ *
+ * @throws \InvalidArgumentException If key does not exist in $this->args.
*/
public function offsetGet($key)
{
diff --git a/src/Symfony/Component/Finder/Expression/Expression.php b/src/Symfony/Component/Finder/Expression/Expression.php
index d2fc7390f33a9..9bae6dd875d4a 100644
--- a/src/Symfony/Component/Finder/Expression/Expression.php
+++ b/src/Symfony/Component/Finder/Expression/Expression.php
@@ -125,9 +125,9 @@ public function isGlob()
}
/**
- * @throws \LogicException
- *
* @return Glob
+ *
+ * @throws \LogicException
*/
public function getGlob()
{
diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php
index 9a57a34b6333d..9574f10d7ed8d 100644
--- a/src/Symfony/Component/Finder/Finder.php
+++ b/src/Symfony/Component/Finder/Finder.php
@@ -133,10 +133,10 @@ public function useBestAdapter()
*
* @param string $name
*
- * @throws \InvalidArgumentException
- *
* @return Finder The current Finder instance
*
+ * @throws \InvalidArgumentException
+ *
* @deprecated since 2.8, to be removed in 3.0.
*/
public function setAdapter($name)
@@ -192,7 +192,7 @@ public function getAdapters()
/**
* Restricts the matching to directories only.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*/
public function directories()
{
@@ -204,7 +204,7 @@ public function directories()
/**
* Restricts the matching to files only.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*/
public function files()
{
@@ -223,7 +223,7 @@ public function files()
*
* @param int $level The depth level expression
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see DepthRangeFilterIterator
* @see NumberComparator
@@ -247,7 +247,7 @@ public function depth($level)
*
* @param string $date A date range string
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see strtotime
* @see DateRangeFilterIterator
@@ -271,7 +271,7 @@ public function date($date)
*
* @param string $pattern A pattern (a regexp, a glob, or a string)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilenameFilterIterator
*/
@@ -287,7 +287,7 @@ public function name($pattern)
*
* @param string $pattern A pattern (a regexp, a glob, or a string)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilenameFilterIterator
*/
@@ -308,7 +308,7 @@ public function notName($pattern)
*
* @param string $pattern A pattern (string or regexp)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilecontentFilterIterator
*/
@@ -329,7 +329,7 @@ public function contains($pattern)
*
* @param string $pattern A pattern (string or regexp)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilecontentFilterIterator
*/
@@ -352,7 +352,7 @@ public function notContains($pattern)
*
* @param string $pattern A pattern (a regexp or a string)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilenameFilterIterator
*/
@@ -375,7 +375,7 @@ public function path($pattern)
*
* @param string $pattern A pattern (a regexp or a string)
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see FilenameFilterIterator
*/
@@ -395,7 +395,7 @@ public function notPath($pattern)
*
* @param string $size A size range string
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SizeRangeFilterIterator
* @see NumberComparator
@@ -412,7 +412,7 @@ public function size($size)
*
* @param string|array $dirs A directory path or an array of directories
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see ExcludeDirectoryFilterIterator
*/
@@ -428,7 +428,7 @@ public function exclude($dirs)
*
* @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see ExcludeDirectoryFilterIterator
*/
@@ -448,7 +448,7 @@ public function ignoreDotFiles($ignoreDotFiles)
*
* @param bool $ignoreVCS Whether to exclude VCS files or not
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see ExcludeDirectoryFilterIterator
*/
@@ -488,7 +488,7 @@ public static function addVCSPattern($pattern)
*
* @param \Closure $closure An anonymous function
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -504,7 +504,7 @@ public function sort(\Closure $closure)
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -520,7 +520,7 @@ public function sortByName()
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -538,7 +538,7 @@ public function sortByType()
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -558,7 +558,7 @@ public function sortByAccessedTime()
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -576,7 +576,7 @@ public function sortByChangedTime()
*
* This can be slow as all the matching files and directories must be retrieved for comparison.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see SortableIterator
*/
@@ -595,7 +595,7 @@ public function sortByModifiedTime()
*
* @param \Closure $closure An anonymous function
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @see CustomFilterIterator
*/
@@ -609,7 +609,7 @@ public function filter(\Closure $closure)
/**
* Forces the following of symlinks.
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*/
public function followLinks()
{
@@ -625,7 +625,7 @@ public function followLinks()
*
* @param bool $ignore
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*/
public function ignoreUnreadableDirs($ignore = true)
{
@@ -639,7 +639,7 @@ public function ignoreUnreadableDirs($ignore = true)
*
* @param string|array $dirs A directory path or an array of directories
*
- * @return Finder The current Finder instance
+ * @return Finder|SplFileInfo[] The current Finder instance
*
* @throws \InvalidArgumentException if one of the directories does not exist
*/
@@ -700,7 +700,7 @@ public function getIterator()
*
* @param mixed $iterator
*
- * @return Finder The finder
+ * @return Finder|SplFileInfo[] The finder
*
* @throws \InvalidArgumentException When the given argument is not iterable.
*/
diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php
index b38680a1bb6ec..5418f7feae919 100644
--- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php
+++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php
@@ -126,7 +126,7 @@ public function reverseTransform($value)
try {
// read timestamp into DateTime object - the formatter delivers in UTC
- $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp));
+ $dateTime = new \DateTime(sprintf('@%s', $timestamp));
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php
index d3ba9cf7bf23b..304ec17e1a493 100644
--- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php
+++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php
@@ -162,9 +162,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $
}
}
- $children = iterator_to_array(new \RecursiveIteratorIterator(
- new InheritDataAwareIterator($form)
- ));
+ $children = iterator_to_array(new \RecursiveIteratorIterator(new InheritDataAwareIterator($form)), false);
while ($it->valid()) {
if ($it->isIndex()) {
@@ -189,7 +187,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $
}
/** @var FormInterface $child */
- foreach ($children as $key => $child) {
+ foreach ($children as $i => $child) {
$childPath = (string) $child->getPropertyPath();
if ($childPath === $chunk) {
$target = $child;
@@ -198,7 +196,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $
continue;
}
- unset($children[$key]);
+ unset($children[$i]);
}
$it->next();
diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php
index 315a3f9f6f20f..0e0d1b73cce1e 100644
--- a/src/Symfony/Component/Form/Form.php
+++ b/src/Symfony/Component/Form/Form.php
@@ -1072,9 +1072,9 @@ public function createView(FormView $parent = null)
*
* @param mixed $value The value to transform
*
- * @throws TransformationFailedException If the value cannot be transformed to "normalized" format
- *
* @return mixed
+ *
+ * @throws TransformationFailedException If the value cannot be transformed to "normalized" format
*/
private function modelToNorm($value)
{
@@ -1098,9 +1098,9 @@ private function modelToNorm($value)
*
* @param string $value The value to reverse transform
*
- * @throws TransformationFailedException If the value cannot be transformed to "model" format
- *
* @return mixed
+ *
+ * @throws TransformationFailedException If the value cannot be transformed to "model" format
*/
private function normToModel($value)
{
@@ -1126,9 +1126,9 @@ private function normToModel($value)
*
* @param mixed $value The value to transform
*
- * @throws TransformationFailedException If the value cannot be transformed to "view" format
- *
* @return mixed
+ *
+ * @throws TransformationFailedException If the value cannot be transformed to "view" format
*/
private function normToView($value)
{
@@ -1161,9 +1161,9 @@ private function normToView($value)
*
* @param string $value The value to reverse transform
*
- * @throws TransformationFailedException If the value cannot be transformed to "normalized" format
- *
* @return mixed
+ *
+ * @throws TransformationFailedException If the value cannot be transformed to "normalized" format
*/
private function viewToNorm($value)
{
diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php
index a099e104595ff..74da4aee1c281 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php
@@ -1542,24 +1542,39 @@ public function testErrorMappingForFormInheritingParentData($target, $childName,
public function testBacktrackIfSeveralSubFormsWithSamePropertyPath()
{
- $violation = $this->getConstraintViolation('data.address[street]');
$parent = $this->getForm('parent');
$child1 = $this->getForm('subform1', 'address');
$child2 = $this->getForm('subform2', 'address');
- $grandChild = $this->getForm('street');
+ $child3 = $this->getForm('subform3', null, null, array(), true);
+ $child4 = $this->getForm('subform4', null, null, array(), true);
+ $grandChild1 = $this->getForm('street');
+ $grandChild2 = $this->getForm('street', '[sub_address1_street]');
+ $grandChild3 = $this->getForm('street', '[sub_address2_street]');
$parent->add($child1);
$parent->add($child2);
- $child2->add($grandChild);
+ $parent->add($child3);
+ $parent->add($child4);
+ $child2->add($grandChild1);
+ $child3->add($grandChild2);
+ $child4->add($grandChild3);
$parent->submit(array());
- $this->mapper->mapViolation($violation, $parent);
+ $violation1 = $this->getConstraintViolation('data.address[street]');
+ $violation2 = $this->getConstraintViolation('data[sub_address1_street]');
+ $violation3 = $this->getConstraintViolation('data[sub_address2_street]');
+ $this->mapper->mapViolation($violation1, $parent);
+ $this->mapper->mapViolation($violation2, $parent);
+ $this->mapper->mapViolation($violation3, $parent);
- // The error occurred on the child of the second form with the same path
$this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
$this->assertCount(0, $child1->getErrors(), $child1->getName().' should not have an error, but has one');
$this->assertCount(0, $child2->getErrors(), $child2->getName().' should not have an error, but has one');
- $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChild->getName().' should have an error, but has none');
+ $this->assertCount(0, $child3->getErrors(), $child3->getName().' should not have an error, but has one');
+ $this->assertCount(0, $child4->getErrors(), $child4->getName().' should not have an error, but has one');
+ $this->assertEquals(array($this->getFormError($violation1, $grandChild1)), iterator_to_array($grandChild1->getErrors()), $grandChild1->getName().' should have an error, but has none');
+ $this->assertEquals(array($this->getFormError($violation2, $grandChild2)), iterator_to_array($grandChild2->getErrors()), $grandChild2->getName().' should have an error, but has none');
+ $this->assertEquals(array($this->getFormError($violation3, $grandChild3)), iterator_to_array($grandChild3->getErrors()), $grandChild3->getName().' should have an error, but has none');
}
}
diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php
index 6a6082fde4e56..b2c12ef381202 100644
--- a/src/Symfony/Component/HttpFoundation/Response.php
+++ b/src/Symfony/Component/HttpFoundation/Response.php
@@ -59,6 +59,7 @@ class Response
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418; // RFC2324
+ const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918
const HTTP_LOCKED = 423; // RFC4918
const HTTP_FAILED_DEPENDENCY = 424; // RFC4918
@@ -115,7 +116,7 @@ class Response
*
* The list of codes is complete according to the
* {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry}
- * (last updated 2015-05-19).
+ * (last updated 2016-03-01).
*
* Unless otherwise noted, the status code is defined in RFC2616.
*
@@ -162,6 +163,7 @@ class Response
416 => 'Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot', // RFC2324
+ 421 => 'Misdirected Request', // RFC7540
422 => 'Unprocessable Entity', // RFC4918
423 => 'Locked', // RFC4918
424 => 'Failed Dependency', // RFC4918
diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
index 06534aa75bf39..1d26e86b9b17b 100644
--- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
+++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
@@ -181,9 +181,9 @@ public function removeCookie($name, $path = '/', $domain = null)
*
* @param string $format
*
- * @throws \InvalidArgumentException When the $format is invalid
- *
* @return array
+ *
+ * @throws \InvalidArgumentException When the $format is invalid
*/
public function getCookies($format = self::COOKIES_FLAT)
{
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
index 4b2f5d27aab41..206f18e77f8d9 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
@@ -24,9 +24,9 @@ interface SessionStorageInterface
/**
* Starts the session.
*
- * @throws \RuntimeException If something goes wrong starting the session.
- *
* @return bool True if started.
+ *
+ * @throws \RuntimeException If something goes wrong starting the session.
*/
public function start();
diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php
index e8795244b176e..0c579d7724846 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php
@@ -30,6 +30,10 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcache class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
+ }
+
parent::setUp();
$this->memcache = $this->getMock('Memcache');
$this->storage = new MemcacheSessionHandler(
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 f51ec8ed63c86..75e4a20e2a8d5 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
@@ -31,6 +31,10 @@ class MemcachedSessionHandlerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcached class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
+ }
+
parent::setUp();
if (version_compare(phpversion('memcached'), '2.2.0', '>=')) {
diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
index 1af321096ebad..9612320976944 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
@@ -135,6 +135,10 @@ public function testReadWriteReadWithNullByte()
public function testReadConvertsStreamToString()
{
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
+ }
+
$pdo = new MockPdo('pgsql');
$pdo->prepareResult = $this->getMock('PDOStatement');
@@ -152,6 +156,10 @@ public function testReadConvertsStreamToString()
public function testReadLockedConvertsStreamToString()
{
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289');
+ }
+
$pdo = new MockPdo('pgsql');
$selectStmt = $this->getMock('PDOStatement');
$insertStmt = $this->getMock('PDOStatement');
diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
index 97aa740962665..4b3e218b85c58 100644
--- a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
+++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
@@ -71,6 +71,11 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
$this->container->set('request', null, 'request');
$this->container->leaveScope('request');
+ throw $e;
+ } catch (\Throwable $e) {
+ $this->container->set('request', null, 'request');
+ $this->container->leaveScope('request');
+
throw $e;
}
diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
index 6075d235b6d83..f794d94e29d45 100644
--- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
+++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
@@ -153,9 +153,9 @@ public function getKernel()
/**
* Gets the Surrogate instance.
*
- * @throws \LogicException
- *
* @return SurrogateInterface A Surrogate instance
+ *
+ * @throws \LogicException
*/
public function getSurrogate()
{
@@ -169,10 +169,10 @@ public function getSurrogate()
/**
* Gets the Esi instance.
*
- * @throws \LogicException
- *
* @return Esi An Esi instance
*
+ * @throws \LogicException
+ *
* @deprecated since version 2.6, to be removed in 3.0. Use getSurrogate() instead
*/
public function getEsi()
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index a95bd97ee3a21..dc5832ed2d505 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -59,11 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
- const VERSION = '2.8.6';
- const VERSION_ID = 20806;
+ const VERSION = '2.8.7';
+ const VERSION_ID = 20807;
const MAJOR_VERSION = 2;
const MINOR_VERSION = 8;
- const RELEASE_VERSION = 6;
+ const RELEASE_VERSION = 7;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '11/2018';
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
index 7fc127e49b647..101782e49079e 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
@@ -127,7 +127,7 @@ public function getUndefinedControllers()
{
return array(
array('foo'),
- array('foo::bar'),
+ array('oof::bar'),
array('stdClass'),
array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar'),
);
diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
index e9b8433c46ef5..8675622891c87 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
@@ -128,7 +128,7 @@ public function testFlush()
$line = __LINE__ - 1;
ob_start();
- $collector = null;
+ $collector->__destruct();
if (PHP_VERSION_ID >= 50400) {
$this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean());
} else {
diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
index 18b5cf6235c69..fbbcf87ed0d46 100644
--- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
+++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
@@ -328,7 +328,7 @@ public static function create($locale = 'en', $style = null, $pattern = null)
* @return string The formatted currency value
*
* @see http://www.php.net/manual/en/numberformatter.formatcurrency.php
- * @see http://www.iso.org/iso/support/faqs/faqs_widely_used_standards/widely_used_standards_other/currency_codes/currency_codes_list-1.htm
+ * @see https://en.wikipedia.org/wiki/ISO_4217#Active_codes
*/
public function formatCurrency($value, $currency)
{
diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
index e0578af71781d..bc763202f228a 100644
--- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php
+++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
@@ -861,6 +861,9 @@ public function offsetGet($option)
} catch (\Exception $e) {
unset($this->calling[$option]);
throw $e;
+ } catch (\Throwable $e) {
+ unset($this->calling[$option]);
+ throw $e;
}
unset($this->calling[$option]);
// END
@@ -963,6 +966,9 @@ public function offsetGet($option)
} catch (\Exception $e) {
unset($this->calling[$option]);
throw $e;
+ } catch (\Throwable $e) {
+ unset($this->calling[$option]);
+ throw $e;
}
unset($this->calling[$option]);
// END
diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php
index 08742df2d9c85..67ea6545891f6 100644
--- a/src/Symfony/Component/Process/Process.php
+++ b/src/Symfony/Component/Process/Process.php
@@ -477,10 +477,10 @@ public function getOutput()
* In comparison with the getOutput method which always return the whole
* output, this one returns the new output since the last call.
*
+ * @return string The process output since the last call
+ *
* @throws LogicException in case the output has been disabled
* @throws LogicException In case the process is not started
- *
- * @return string The process output since the last call
*/
public function getIncrementalOutput()
{
@@ -536,10 +536,10 @@ public function getErrorOutput()
* whole error output, this one returns the new error output since the last
* call.
*
+ * @return string The process error output since the last call
+ *
* @throws LogicException in case the output has been disabled
* @throws LogicException In case the process is not started
- *
- * @return string The process error output since the last call
*/
public function getIncrementalErrorOutput()
{
diff --git a/src/Symfony/Component/PropertyAccess/StringUtil.php b/src/Symfony/Component/PropertyAccess/StringUtil.php
index 248a6483d8b0a..caa8c3d7e1a0d 100644
--- a/src/Symfony/Component/PropertyAccess/StringUtil.php
+++ b/src/Symfony/Component/PropertyAccess/StringUtil.php
@@ -124,6 +124,9 @@ class StringUtil
// chateaux (chateau)
array('xuae', 4, false, true, 'eau'),
+
+ // people (person)
+ array('elpoep', 6, true, true, 'person'),
);
/**
diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
index f3c7b405c1758..3f1ef1c040a6a 100644
--- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
@@ -242,7 +242,9 @@ public function testSetValueThrowsNoExceptionIfIndexNotFoundAndIndexExceptionsEn
*/
public function testSetValueThrowsExceptionIfNotArrayAccess()
{
- $this->propertyAccessor->setValue(new \stdClass(), '[index]', 'Updated');
+ $object = new \stdClass();
+
+ $this->propertyAccessor->setValue($object, '[index]', 'Updated');
}
public function testSetValueUpdatesMagicSet()
@@ -259,7 +261,9 @@ public function testSetValueUpdatesMagicSet()
*/
public function testSetValueThrowsExceptionIfThereAreMissingParameters()
{
- $this->propertyAccessor->setValue(new TestClass('Bernhard'), 'publicAccessorWithMoreRequiredParameters', 'Updated');
+ $object = new TestClass('Bernhard');
+
+ $this->propertyAccessor->setValue($object, 'publicAccessorWithMoreRequiredParameters', 'Updated');
}
/**
@@ -527,7 +531,9 @@ public function testIsWritableForReferenceChainIssue($object, $path, $value)
*/
public function testThrowTypeError()
{
- $this->propertyAccessor->setValue(new TypeHinted(), 'date', 'This is a string, \DateTime expected.');
+ $object = new TypeHinted();
+
+ $this->propertyAccessor->setValue($object, 'date', 'This is a string, \DateTime expected.');
}
public function testSetTypeHint()
diff --git a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php
index 0fd6bb69b2956..983e355cb9038 100644
--- a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php
+++ b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php
@@ -107,6 +107,8 @@ public function singularifyProvider()
array('objectives', 'objective'),
array('oxen', 'ox'),
array('parties', 'party'),
+ array('people', 'person'),
+ array('persons', 'person'),
array('phenomena', array('phenomenon', 'phenomenum')),
array('photos', 'photo'),
array('pianos', 'piano'),
diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
index a3a7e0e5ae50e..b8fc03615f968 100644
--- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
+++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
@@ -112,7 +112,24 @@ protected function findClass($file)
}
if (T_CLASS === $token[0]) {
- $class = true;
+ // Skip usage of ::class constant
+ $isClassConstant = false;
+ for ($j = $i - 1; $j > 0; --$j) {
+ if (!isset($tokens[$j][1])) {
+ break;
+ }
+
+ if (T_DOUBLE_COLON === $tokens[$j][0]) {
+ $isClassConstant = true;
+ break;
+ } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
+ break;
+ }
+ }
+
+ if (!$isClassConstant) {
+ $class = true;
+ }
}
if (T_NAMESPACE === $token[0]) {
diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooTrait.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooTrait.php
new file mode 100644
index 0000000000000..ee8f4b071a368
--- /dev/null
+++ b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooTrait.php
@@ -0,0 +1,13 @@
+loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php');
}
+ /**
+ * @requires PHP 5.4
+ */
+ public function testLoadTraitWithClassConstant()
+ {
+ $this->reader->expects($this->never())->method('getClassAnnotation');
+
+ $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooTrait.php');
+ }
+
/**
* @requires PHP 5.6
*/
diff --git a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
index f8f17b4f723e6..352ba584a7638 100644
--- a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
+++ b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
@@ -59,7 +59,7 @@ public function supportsDecoding($format)
*
* @return DecoderInterface
*
- * @throws RuntimeException if no decoder is found
+ * @throws RuntimeException If no decoder is found.
*/
private function getDecoder($format)
{
diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
index d1f09f6eaf94e..4c17fb6b8d859 100644
--- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
+++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
@@ -461,6 +461,8 @@ private function needsCdataWrapping($val)
* @param mixed $val
*
* @return bool
+ *
+ * @throws UnexpectedValueException
*/
private function selectNodeType(\DOMNode $node, $val)
{
diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php
index 86c270299ee47..8ad1386a6cbd4 100644
--- a/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php
+++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php
@@ -33,6 +33,8 @@ interface DenormalizableInterface
* @param string|null $format The format is optionally given to be able to denormalize differently
* based on different input formats
* @param array $context options for denormalizing
+ *
+ * @return object
*/
public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array());
}
diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php
index b9fefe887a44a..e19fe5ce58576 100644
--- a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php
+++ b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php
@@ -33,7 +33,7 @@ interface NormalizableInterface
* based on different output formats.
* @param array $context Options for normalizing this object
*
- * @return array|string|bool|int|float|null
+ * @return array|scalar
*/
public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array());
}
diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
index 2a51d631b1624..f4bd355232b0b 100644
--- a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
+++ b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
@@ -25,7 +25,7 @@ interface NormalizerInterface
* @param string $format format the normalization result will be encoded as
* @param array $context Context options for the normalizer
*
- * @return array|string|bool|int|float|null
+ * @return array|scalar
*/
public function normalize($object, $format = null, array $context = array());
diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
index f7df6446b97ba..3d5857cccdc21 100644
--- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
@@ -336,6 +336,19 @@ public function testIgnoredAttributes()
);
}
+ public function testIgnoredAttributesDenormalize()
+ {
+ $this->normalizer->setIgnoredAttributes(array('fooBar', 'bar', 'baz'));
+
+ $obj = new ObjectDummy();
+ $obj->setFoo('foo');
+
+ $this->assertEquals(
+ $obj,
+ $this->normalizer->denormalize(array('fooBar' => 'fooBar', 'foo' => 'foo', 'baz' => 'baz'), __NAMESPACE__.'\ObjectDummy')
+ );
+ }
+
public function provideCallbacks()
{
return array(
diff --git a/src/Symfony/Component/Stopwatch/StopwatchEvent.php b/src/Symfony/Component/Stopwatch/StopwatchEvent.php
index 930722d2f598c..957a5d0dae0a8 100644
--- a/src/Symfony/Component/Stopwatch/StopwatchEvent.php
+++ b/src/Symfony/Component/Stopwatch/StopwatchEvent.php
@@ -87,8 +87,6 @@ public function start()
/**
* Stops the last started event period.
*
- * @throws \LogicException When start wasn't called before stopping
- *
* @return StopwatchEvent The event
*
* @throws \LogicException When stop() is called without a matching call to start()
diff --git a/src/Symfony/Component/Translation/Extractor/AbstractFileExtractor.php b/src/Symfony/Component/Translation/Extractor/AbstractFileExtractor.php
index 196bc3341060a..57fd4938d22cf 100644
--- a/src/Symfony/Component/Translation/Extractor/AbstractFileExtractor.php
+++ b/src/Symfony/Component/Translation/Extractor/AbstractFileExtractor.php
@@ -54,9 +54,9 @@ private function toSplFileInfo($file)
/**
* @param string $file
*
- * @throws \InvalidArgumentException
- *
* @return bool
+ *
+ * @throws \InvalidArgumentException
*/
protected function isFile($file)
{
diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php
index bdca11099d704..a02f544a9132a 100644
--- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php
+++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php
@@ -160,10 +160,13 @@ private function utf8ToCharset($content, $encoding = null)
}
/**
+ * Validates and parses the given file into a DOMDocument.
+ *
* @param string $file
* @param \DOMDocument $dom
* @param string $schema source of the schema
*
+ * @throws \RuntimeException
* @throws InvalidResourceException
*/
private function validateSchema($file, \DOMDocument $dom, $schema)
diff --git a/src/Symfony/Component/Translation/TranslatorBagInterface.php b/src/Symfony/Component/Translation/TranslatorBagInterface.php
index 6f650b5ee0f88..14fbb17f5e46e 100644
--- a/src/Symfony/Component/Translation/TranslatorBagInterface.php
+++ b/src/Symfony/Component/Translation/TranslatorBagInterface.php
@@ -23,9 +23,9 @@ interface TranslatorBagInterface
*
* @param string|null $locale The locale or null to use the default
*
- * @throws \InvalidArgumentException If the locale contains invalid characters
- *
* @return MessageCatalogueInterface
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
*/
public function getCatalogue($locale = null);
}
diff --git a/src/Symfony/Component/Translation/TranslatorInterface.php b/src/Symfony/Component/Translation/TranslatorInterface.php
index 869e0b900442d..6916c335bd426 100644
--- a/src/Symfony/Component/Translation/TranslatorInterface.php
+++ b/src/Symfony/Component/Translation/TranslatorInterface.php
@@ -26,9 +26,9 @@ interface TranslatorInterface
* @param string|null $domain The domain for the message or null to use the default
* @param string|null $locale The locale or null to use the default
*
- * @throws \InvalidArgumentException If the locale contains invalid characters
- *
* @return string The translated string
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null);
@@ -41,9 +41,9 @@ public function trans($id, array $parameters = array(), $domain = null, $locale
* @param string|null $domain The domain for the message or null to use the default
* @param string|null $locale The locale or null to use the default
*
- * @throws \InvalidArgumentException If the locale contains invalid characters
- *
* @return string The translated string
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);
diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
index f8b9c1077790a..58fd202c0ea16 100644
--- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
@@ -122,6 +122,8 @@ public function dump(Data $data, $output = null)
$this->dumpLine(-1);
} catch (\Exception $exception) {
// Re-thrown below
+ } catch (\Throwable $exception) {
+ // Re-thrown below
}
if ($output) {
$this->setOutput($prevOutput);
diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php
index 21351a5c34fc9..9bd9389c07483 100644
--- a/src/Symfony/Component/Yaml/Dumper.php
+++ b/src/Symfony/Component/Yaml/Dumper.php
@@ -58,7 +58,7 @@ public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType =
if ($inline <= 0 || !is_array($input) || empty($input)) {
$output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport);
} else {
- $isAHash = array_keys($input) !== range(0, count($input) - 1);
+ $isAHash = Inline::isHash($input);
foreach ($input as $key => $value) {
$willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php
index bb2db360f7e35..717cbfd5ec8f2 100644
--- a/src/Symfony/Component/Yaml/Inline.php
+++ b/src/Symfony/Component/Yaml/Inline.php
@@ -157,6 +157,28 @@ public static function dump($value, $exceptionOnInvalidType = false, $objectSupp
}
}
+ /**
+ * Check if given array is hash or just normal indexed array.
+ *
+ * @internal
+ *
+ * @param array $value The PHP array to check
+ *
+ * @return bool true if value is hash array, false otherwise
+ */
+ public static function isHash(array $value)
+ {
+ $expectedKey = 0;
+
+ foreach ($value as $key => $val) {
+ if ($key !== $expectedKey++) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Dumps a PHP array to a YAML string.
*
@@ -169,11 +191,7 @@ public static function dump($value, $exceptionOnInvalidType = false, $objectSupp
private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport)
{
// array
- $keys = array_keys($value);
- $keysCount = count($keys);
- if ((1 === $keysCount && '0' == $keys[0])
- || ($keysCount > 1 && array_reduce($keys, function ($v, $w) { return (int) $v + $w; }, 0) === $keysCount * ($keysCount - 1) / 2)
- ) {
+ if ($value && !self::isHash($value)) {
$output = array();
foreach ($value as $val) {
$output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport);
@@ -182,7 +200,7 @@ private static function dumpArray($value, $exceptionOnInvalidType, $objectSuppor
return sprintf('[%s]', implode(', ', $output));
}
- // mapping
+ // hash
$output = array();
foreach ($value as $key => $val) {
$output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport));
diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php
index 41134e6b6c72e..3c02243d9025d 100644
--- a/src/Symfony/Component/Yaml/Parser.php
+++ b/src/Symfony/Component/Yaml/Parser.php
@@ -25,6 +25,7 @@ class Parser
const FOLDED_SCALAR_PATTERN = self::BLOCK_SCALAR_HEADER_PATTERN;
private $offset = 0;
+ private $totalNumberOfLines;
private $lines = array();
private $currentLineNb = -1;
private $currentLine = '';
@@ -33,11 +34,13 @@ class Parser
/**
* Constructor.
*
- * @param int $offset The offset of YAML document (used for line numbers in error messages)
+ * @param int $offset The offset of YAML document (used for line numbers in error messages)
+ * @param int|null $totalNumberOfLines The overall number of lines being parsed
*/
- public function __construct($offset = 0)
+ public function __construct($offset = 0, $totalNumberOfLines = null)
{
$this->offset = $offset;
+ $this->totalNumberOfLines = $totalNumberOfLines;
}
/**
@@ -62,6 +65,10 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
$value = $this->cleanup($value);
$this->lines = explode("\n", $value);
+ if (null === $this->totalNumberOfLines) {
+ $this->totalNumberOfLines = count($this->lines);
+ }
+
if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('UTF-8');
@@ -83,7 +90,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
$isRef = $mergeNode = false;
if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) {
if ($context && 'mapping' == $context) {
- throw new ParseException('You cannot define a sequence item when in a mapping');
+ throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine);
}
$context = 'sequence';
@@ -95,7 +102,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
// array
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap);
} else {
@@ -104,7 +111,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
) {
// this is a compact notation element, add to next block and parse
$c = $this->getRealCurrentLineNb();
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$block = $values['value'];
@@ -122,7 +129,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
}
} elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) {
if ($context && 'sequence' == $context) {
- throw new ParseException('You cannot define a mapping item when in a sequence');
+ throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine);
}
$context = 'mapping';
@@ -169,7 +176,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
$value = $this->getNextEmbedBlock();
}
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap);
@@ -220,7 +227,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
}
} else {
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap);
// Spec: Keys MUST be unique; first one wins.
@@ -243,7 +250,7 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
} else {
// multiple documents are not supported
if ('---' === $this->currentLine) {
- throw new ParseException('Multiple documents are not supported.');
+ throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine);
}
// 1-liner optionally followed by newline(s)
@@ -490,7 +497,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob
}
if (!array_key_exists($value, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
+ throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine);
}
return $this->refs[$value];
@@ -585,6 +592,8 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0)
if ($notEOF) {
$blockLines[] = '';
$this->moveToPreviousLine();
+ } elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) {
+ $blockLines[] = '';
}
// folded style
@@ -691,6 +700,11 @@ private function isCurrentLineComment()
return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
}
+ private function isCurrentLineLastLineInDocument()
+ {
+ return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1);
+ }
+
/**
* Cleanups a YAML string to be parsed.
*
@@ -768,7 +782,7 @@ private function isNextLineUnIndentedCollection()
*/
private function isStringUnIndentedCollectionItem()
{
- return 0 === strpos($this->currentLine, '- ');
+ return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- ');
}
/**
diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php
index f0f9b96b851c1..e349bfcc227a6 100644
--- a/src/Symfony/Component/Yaml/Tests/InlineTest.php
+++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php
@@ -220,6 +220,24 @@ public function getScalarIndicators()
return array(array('|'), array('>'));
}
+ /**
+ * @dataProvider getDataForIsHash
+ */
+ public function testIsHash($array, $expected)
+ {
+ $this->assertSame($expected, Inline::isHash($array));
+ }
+
+ public function getDataForIsHash()
+ {
+ return array(
+ array(array(), false),
+ array(array(1, 2, 3), false),
+ array(array(2 => 1, 1 => 2, 0 => 3), true),
+ array(array('foo' => 1, 'bar' => 2), true),
+ );
+ }
+
public function getTestsForParse()
{
return array(
@@ -426,6 +444,8 @@ public function getTestsForDump()
array('[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]', array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo')))),
array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
+
+ array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))),
);
}
}
diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php
index 8fea5e8e84438..d05ff391fcd12 100644
--- a/src/Symfony/Component/Yaml/Tests/ParserTest.php
+++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php
@@ -596,7 +596,7 @@ public function testShortcutKeyUnindentedCollectionException()
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage Multiple documents are not supported.
+ * @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/
*/
public function testMultipleDocumentsNotSupportedException()
{
@@ -628,6 +628,34 @@ public function testSequenceInAMapping()
);
}
+ public function testSequenceInMappingStartedBySingleDashLine()
+ {
+ $yaml = << array(
+ array(
+ 'b' => array(
+ array(
+ 'bar' => 'baz',
+ ),
+ ),
+ ),
+ 'foo',
+ ),
+ 'd' => 'e',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
@@ -993,6 +1021,7 @@ public function getCommentLikeStringInScalarBlockData()
foo
# bar
baz
+
EOT
,
),
@@ -1021,7 +1050,7 @@ public function getCommentLikeStringInScalarBlockData()
$expected = array(
'foo' => array(
'bar' => array(
- 'scalar-block' => 'line1 line2>',
+ 'scalar-block' => "line1 line2>\n",
),
'baz' => array(
'foobar' => null,