diff --git a/.github/rm-invalid-lowest-lock-files.php b/.github/rm-invalid-lowest-lock-files.php
new file mode 100644
index 0000000000000..c71463262171a
--- /dev/null
+++ b/.github/rm-invalid-lowest-lock-files.php
@@ -0,0 +1,159 @@
+ array(), 'packages-dev' => array());
+ $composerJsons[$composerJson['name']] = array($dir, $composerLock['packages'] + $composerLock['packages-dev'], getRelevantContent($composerJson));
+}
+
+$referencedCommits = array();
+
+foreach ($composerJsons as list($dir, $lockedPackages)) {
+ foreach ($lockedPackages as $lockedJson) {
+ if (0 !== strpos($version = $lockedJson['version'], 'dev-') && '-dev' !== substr($version, -4)) {
+ continue;
+ }
+
+ if (!isset($composerJsons[$name = $lockedJson['name']])) {
+ echo "$dir/composer.lock references missing $name.\n";
+ @unlink($dir.'/composer.lock');
+ continue 2;
+ }
+
+ if (isset($composerJsons[$name][2]['repositories']) && !isset($lockedJson[$key]['repositories'])) {
+ // the locked package has been patched locally but the lock references a commit,
+ // which means the referencing package itself is not modified
+ continue;
+ }
+
+ foreach (array('minimum-stability', 'prefer-stable') as $key) {
+ if (array_key_exists($key, $composerJsons[$name][2])) {
+ $lockedJson[$key] = $composerJsons[$name][2][$key];
+ }
+ }
+
+ // use weak comparison to ignore ordering
+ if (getRelevantContent($lockedJson) != $composerJsons[$name][2]) {
+ echo "$dir/composer.lock is not in sync with $name.\n";
+ @unlink($dir.'/composer.lock');
+ continue 2;
+ }
+
+ if ($lockedJson['dist']['reference']) {
+ $referencedCommits[$name][$lockedJson['dist']['reference']][] = $dir;
+ }
+ }
+}
+
+if (!$referencedCommits || (isset($_SERVER['TRAVIS_PULL_REQUEST']) && 'false' !== $_SERVER['TRAVIS_PULL_REQUEST'])) {
+ // cached commits cannot be stale for PRs
+ return;
+}
+
+@mkdir($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org', 0777, true);
+
+$ch = null;
+$mh = curl_multi_init();
+$sh = curl_share_init();
+curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
+curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
+$chs = array();
+
+foreach ($referencedCommits as $name => $dirsByCommit) {
+ $chs[] = $ch = array(curl_init(), fopen($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org/provider-'.strtr($name, '/', '$').'.json', 'wb'));
+ curl_setopt($ch[0], CURLOPT_URL, 'https://repo.packagist.org/p/'.$name.'.json');
+ curl_setopt($ch[0], CURLOPT_FILE, $ch[1]);
+ curl_setopt($ch[0], CURLOPT_SHARE, $sh);
+ curl_multi_add_handle($mh, $ch[0]);
+}
+
+do {
+ curl_multi_exec($mh, $active);
+ curl_multi_select($mh);
+} while ($active);
+
+foreach ($chs as list($ch, $fd)) {
+ curl_multi_remove_handle($mh, $ch);
+ curl_close($ch);
+ fclose($fd);
+}
+
+foreach ($referencedCommits as $name => $dirsByCommit) {
+ $repo = file_get_contents($_SERVER['HOME'].'/.cache/composer/repo/https---repo.packagist.org/provider-'.strtr($name, '/', '$').'.json');
+ $repo = json_decode($repo, true);
+
+ foreach ($repo['packages'][$name] as $version) {
+ unset($referencedCommits[$name][$version['source']['reference']]);
+ }
+}
+
+foreach ($referencedCommits as $name => $dirsByCommit) {
+ foreach ($dirsByCommit as $dirs) {
+ foreach ($dirs as $dir) {
+ if (file_exists($dir.'/composer.lock')) {
+ echo "$dir/composer.lock references old commit for $name.\n";
+ @unlink($dir.'/composer.lock');
+ }
+ }
+ }
+}
diff --git a/.travis.yml b/.travis.yml
index f3f3660ef8dfe..719785fc18af3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,8 +24,7 @@ matrix:
sudo: required
group: edge
- php: 5.5
- - php: 5.6
- - php: 7.0
+ env: php_extra="5.6 7.0"
- php: 7.1
env: deps=high
- php: 7.2
@@ -42,21 +41,39 @@ services:
- memcached
- mongodb
- redis-server
+ - docker
before_install:
+ - |
+ # Start Redis cluster
+ docker pull grokzen/redis-cluster:4.0.8
+ docker run -d -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 --name redis-cluster grokzen/redis-cluster:4.0.8
+ export REDIS_CLUSTER_HOSTS='localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005'
+
- |
# General configuration
+ set -e
stty cols 120
mkdir /tmp/slapd
slapd -f src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf -h ldap://localhost:3389 &
- PHP=$TRAVIS_PHP_VERSION
[ -d ~/.composer ] || mkdir ~/.composer
cp .composer/* ~/.composer/
export PHPUNIT=$(readlink -f ./phpunit)
export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data"
export COMPOSER_UP='composer update --no-progress --no-suggest --ansi'
+ export COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n')
+ find ~/.phpenv -name xdebug.ini -delete
- nanoseconds() {
+ if [[ $TRAVIS_PHP_VERSION = 5.* || $TRAVIS_PHP_VERSION = hhvm* ]]; then
+ composer () {
+ $HOME/.phpenv/versions/7.1/bin/php $HOME/.phpenv/versions/7.1/bin/composer config platform.php $(echo ' > $INI
- echo memory_limit = -1 >> $INI
- echo session.gc_probability = 0 >> $INI
- echo opcache.enable_cli = 1 >> $INI
- echo hhvm.jit = 0 >> $INI
- echo apc.enable_cli = 1 >> $INI
- echo extension = redis.so >> $INI
- echo extension = memcached.so >> $INI
- [[ $PHP = 5.* ]] && echo extension = memcache.so >> $INI
- if [[ $PHP = 5.* ]]; then
- echo extension = mongo.so >> $INI
- fi
-
# tpecl is a helper to compile and cache php extensions
tpecl () {
local ext_name=$1
@@ -122,6 +119,7 @@ before_install:
if [[ -e $ext_cache/$ext_so ]]; then
echo extension = $ext_cache/$ext_so >> $INI
else
+ rm ~/.pearrc /tmp/pear 2>/dev/null || true
mkdir -p $ext_cache
echo yes | pecl install -f $ext_name &&
cp $ext_dir/$ext_so $ext_cache
@@ -129,36 +127,62 @@ before_install:
}
export -f tpecl
- # Matrix lines for intermediate PHP versions are skipped for pull requests
- if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then
- deps=skip
- skip=1
- else
- COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n')
- fi
-
- |
# Install sigchild-enabled PHP to test the Process component on the lowest PHP matrix line
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then
+ if [[ ! $deps && $TRAVIS_PHP_VERSION = ${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
+ - |
+ # php.ini configuration
+ for PHP in $TRAVIS_PHP_VERSION $php_extra; do
+ if [[ $PHP = hhvm* ]]; then
+ INI=/etc/hhvm/php.ini
+ else
+ phpenv global $PHP 2>/dev/null || (cd / && wget https://s3.amazonaws.com/travis-php-archives/binaries/ubuntu/14.04/x86_64/php-$PHP.tar.bz2 -O - | tar -xj)
+ INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini
+ fi
+ echo date.timezone = Europe/Paris >> $INI
+ echo memory_limit = -1 >> $INI
+ echo session.gc_probability = 0 >> $INI
+ echo opcache.enable_cli = 1 >> $INI
+ echo hhvm.jit = 0 >> $INI
+ echo apc.enable_cli = 1 >> $INI
+ echo extension = redis.so >> $INI
+ echo extension = memcached.so >> $INI
+ if [[ $PHP = 5.* ]]; then
+ echo extension = memcache.so >> $INI
+ echo extension = mongo.so >> $INI
+ fi
+ done
+
- |
# Install extra PHP extensions
- if [[ ! $skip && $PHP = 5.* ]]; then
- ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI")
- tfold ext.apcu tpecl apcu-4.0.11 apcu.so $INI
- elif [[ ! $skip && $PHP = 7.* ]]; then
- # install libsodium
- sudo add-apt-repository ppa:ondrej/php -y
- sudo apt-get update -q
- sudo apt-get install libsodium-dev -y
-
- tfold ext.apcu tpecl apcu-5.1.6 apcu.so $INI
- tfold ext.libsodium tpecl libsodium sodium.so $INI
- tfold ext.mongodb tpecl mongodb-1.5.0 mongodb.so $INI
- fi
+ for PHP in $TRAVIS_PHP_VERSION $php_extra; do
+ if [[ $PHP = hhvm* ]]; then
+ continue
+ fi
+ export PHP=$PHP
+ phpenv global $PHP
+ INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini
+ if [[ $PHP = 5.* ]]; then
+ tfold ext.apcu tpecl apcu-4.0.11 apcu.so $INI
+ [[ $deps ]] && continue
+ ext_cache=~/php-ext/$(php -r "echo basename(ini_get('extension_dir'));")/symfony_debug.so
+ [[ -e $ext_cache ]] || (tfold ext.symfony_debug "cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && mv modules/symfony_debug.so $ext_cache && phpize --clean")
+ echo extension = $ext_cache >> $INI
+ elif [[ $PHP = 7.* ]]; then
+ # install libsodium
+ sudo add-apt-repository ppa:ondrej/php -y
+ sudo apt-get update -q
+ sudo apt-get install libsodium-dev -y
+
+ tfold ext.apcu tpecl apcu-5.1.6 apcu.so $INI
+ tfold ext.libsodium tpecl libsodium sodium.so $INI
+ tfold ext.mongodb tpecl mongodb-1.5.0 mongodb.so $INI
+ fi
+ done
- |
# Load fixtures
@@ -172,7 +196,7 @@ install:
# Create local composer packages for each patched components and reference them in composer.json files when cross-testing components
if [[ ! $deps ]]; then
php .github/build-packages.php HEAD^ src/Symfony/Bridge/PhpUnit
- elif [[ ! $skip ]]; then
+ else
export SYMFONY_DEPRECATIONS_HELPER=weak &&
cp composer.json composer.json.orig &&
echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json &&
@@ -188,46 +212,67 @@ install:
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')
- elif [[ ! $skip ]]; then
+ else
SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*')
fi
+ - |
+ # Install symfony/flex
+ if [[ $deps = low ]]; then
+ export SYMFONY_REQUIRE='>=2.3'
+ else
+ export SYMFONY_REQUIRE=">=$SYMFONY_VERSION"
+ fi
+ composer global require --no-progress --no-scripts --no-plugins symfony/flex dev-master
+
- |
# Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one
[[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]] && LEGACY=,legacy
export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev
- if [[ ! $skip && $deps ]]; then mv composer.json.phpunit composer.json; fi
-
- if [[ ! $skip && $PHP = 7.* ]]; then
- ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; composer require --dev --no-update mongodb/mongodb)
- fi
+ if [[ $deps ]]; then mv composer.json.phpunit composer.json; fi
- - if [[ ! $skip ]]; then $COMPOSER_UP; fi
- - if [[ ! $skip ]]; then ./phpunit install; fi
- |
# phpinfo
- if [[ ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
+ if [[ ! $TRAVIS_PHP_VERSION = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
- |
run_tests () {
set -e
- if [[ $skip ]]; then
+ export PHP=$1
+ if [[ $PHP != $TRAVIS_PHP_VERSION && $TRAVIS_PULL_REQUEST != false ]]; then
echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m"
- elif [[ $deps = high ]]; then
+ break
+ fi
+ phpenv global ${PHP/hhvm*/hhvm}
+ if [[ $PHP = 7.* ]]; then
+ ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; composer config platform.ext-mongodb 1.5.0; composer require --dev --no-update mongodb/mongodb)
+ fi
+ tfold 'composer update' $COMPOSER_UP
+ if [[ $TRAVIS_PHP_VERSION = 5.* || $TRAVIS_PHP_VERSION = hhvm* ]]; then
+ tfold 'phpunit install' 'composer global remove symfony/flex && ./phpunit install && composer global require --no-progress --no-scripts --no-plugins symfony/flex dev-master'
+ else
+ tfold 'phpunit install' ./phpunit install
+ fi
+ if [[ $deps = high ]]; then
echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'"
elif [[ $deps = low ]]; then
- echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'"
+ [[ -e ~/php-ext/composer-lowest.lock.tar ]] && tar -xf ~/php-ext/composer-lowest.lock.tar
+ tar -cf ~/php-ext/composer-lowest.lock.tar --files-from /dev/null
+ php .github/rm-invalid-lowest-lock-files.php $COMPONENTS
+ echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ([ -e composer.lock ] && ${COMPOSER_UP/update/install} || $COMPOSER_UP --prefer-lowest --prefer-stable) && $PHPUNIT_X'"
+ echo "$COMPONENTS" | xargs -n1 -I{} tar --append -f ~/php-ext/composer-lowest.lock.tar {}/composer.lock
elif [[ $PHP = hhvm* ]]; then
$PHPUNIT --exclude-group no-hhvm,benchmark,intl-data
else
echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}"
- tfold tty-group $PHPUNIT --group tty
+ tfold src/Symfony/Component/Console.tty $PHPUNIT src/Symfony/Component/Console --group tty
if [[ $PHP = ${MIN_PHP%.*} ]]; then
+ export PHP=$MIN_PHP
echo -e "1\\n0" | xargs -I{} bash -c "tfold src/Symfony/Component/Process.sigchild{} SYMFONY_DEPRECATIONS_HELPER=weak ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/"
fi
fi
}
script:
- - (run_tests)
+ - for PHP in $TRAVIS_PHP_VERSION $php_extra; do (run_tests $PHP); done
diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md
index f0cde9e267b62..567f31a8c12c3 100644
--- a/CHANGELOG-3.4.md
+++ b/CHANGELOG-3.4.md
@@ -7,6 +7,21 @@ in 3.4 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.4.0...v3.4.1
+* 3.4.15 (2018-08-28)
+
+ * bug #28278 [HttpFoundation] Fix unprepared BinaryFileResponse sends empty file (wackymole)
+ * bug #28284 [PhpUnitBridge] keep compat with composer 1.0 (nicolas-grekas)
+ * bug #28241 [HttpKernel] fix forwarding trusted headers as server parameters (nicolas-grekas)
+ * bug #28220 [PropertyAccess] fix type error handling when writing values (xabbuh)
+ * bug #28249 [Cache] enable Memcached::OPT_TCP_NODELAY to fix perf of misses (nicolas-grekas)
+ * bug #28252 [DoctrineBridge] support __toString as documented for UniqueEntityValidator (dmaicher)
+ * bug #28100 [Security] Call AccessListener after LogoutListener (chalasr)
+ * bug #28060 [DI] Fix false-positive circular ref leading to wrong exceptions or infinite loops at runtime (nicolas-grekas)
+ * bug #28144 [HttpFoundation] fix false-positive ConflictingHeadersException (nicolas-grekas)
+ * bug #28012 [PropertyInfo] Allow nested collections (jderusse)
+ * bug #28055 [PropertyInfo] Allow nested collections (jderusse)
+ * bug #28083 Remove the Expires header when calling Response::expire() (javiereguiluz)
+
* 3.4.14 (2018-08-01)
* security #cve-2018-14774 [HttpKernel] fix trusted headers management in HttpCache and InlineFragmentRenderer (nicolas-grekas)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index b6eef0b63198c..629d8b80c98a3 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -24,18 +24,18 @@ Symfony is the result of the work of many people who made the code better
- Hugo Hamon (hhamon)
- Abdellatif Ait boudad (aitboudad)
- Romain Neutron (romain)
- - Pascal Borreli (pborreli)
- Roland Franssen (ro0)
+ - Pascal Borreli (pborreli)
- Wouter De Jong (wouterj)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
- Martin Hasoň (hason)
- Jeremy Mikola (jmikola)
+ - Samuel ROZE (sroze)
- Jean-François Simon (jfsimon)
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- - Samuel ROZE (sroze)
- Jules Pietri (heah)
- Eriksen Costa (eriksencosta)
- Guilhem Niot (energetick)
@@ -52,9 +52,9 @@ Symfony is the result of the work of many people who made the code better
- stealth35 (stealth35)
- Alexander Mols (asm89)
- Bulat Shakirzyanov (avalanche123)
+ - Dany Maillard (maidmaid)
- Peter Rehm (rpet)
- Matthias Pigulla (mpdude)
- - Dany Maillard (maidmaid)
- Saša Stamenković (umpirsky)
- Kevin Bond (kbond)
- Tobias Nyholm (tobias)
@@ -63,21 +63,21 @@ Symfony is the result of the work of many people who made the code better
- Miha Vrhovnik
- Diego Saint Esteben (dii3g0)
- Alexander M. Turek (derrabus)
+ - Jérémy DERUSSÉ (jderusse)
- Konstantin Kudryashov (everzet)
- Bilal Amarni (bamarni)
- - Jérémy DERUSSÉ (jderusse)
- Florin Patan (florinpatan)
- - Mathieu Piot (mpiot)
- Gábor Egyed (1ed)
+ - Mathieu Piot (mpiot)
- Michel Weimerskirch (mweimerskirch)
- Titouan Galopin (tgalopin)
- Andrej Hudec (pulzarraider)
- Eric Clemmons (ericclemmons)
- Jáchym Toušek (enumag)
- Charles Sarrazin (csarrazi)
+ - David Maicher (dmaicher)
- Konstantin Myakshin (koc)
- Christian Raue
- - David Maicher (dmaicher)
- Arnout Boks (aboks)
- Deni
- Henrik Westphal (snc)
@@ -99,11 +99,11 @@ Symfony is the result of the work of many people who made the code better
- Fran Moreno (franmomu)
- Antoine Hérault (herzult)
- Paráda József (paradajozsef)
+ - Grégoire Paris (greg0ire)
- Arnaud Le Blanc (arnaud-lb)
- Maxime STEINHAUSSER
- Michal Piotrowski (eventhorizon)
- Tim Nagel (merk)
- - Grégoire Paris (greg0ire)
- Brice BERNARD (brikou)
- Valentin Udaltsov (vudaltsov)
- gadelat (gadelat)
@@ -124,6 +124,7 @@ Symfony is the result of the work of many people who made the code better
- Fabien Pennequin (fabienpennequin)
- Gordon Franke (gimler)
- Eric GELOEN (gelo)
+ - Sebastiaan Stok (sstok)
- Lars Strojny (lstrojny)
- Daniel Wehner (dawehner)
- Tugdual Saunier (tucksaun)
@@ -131,7 +132,6 @@ Symfony is the result of the work of many people who made the code better
- Théo FIDRY (theofidry)
- Robert Schönthal (digitalkaoz)
- Florian Lonqueu-Brochard (florianlb)
- - Sebastiaan Stok (sstok)
- Stefano Sala (stefano.sala)
- Jérôme Vasseur (jvasseur)
- Evgeniy (ewgraf)
@@ -144,6 +144,7 @@ Symfony is the result of the work of many people who made the code better
- Hidenori Goto (hidenorigoto)
- Chris Wilkinson (thewilkybarkid)
- Arnaud Kleinpeter (nanocom)
+ - Jannik Zschiesche (apfelbox)
- Guilherme Blanco (guilhermeblanco)
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
@@ -170,7 +171,6 @@ Symfony is the result of the work of many people who made the code better
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
- Artur Kotyrba
- - Jannik Zschiesche (apfelbox)
- GDIBass
- jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent)
- James Halsall (jaitsu)
@@ -192,6 +192,7 @@ Symfony is the result of the work of many people who made the code better
- SpacePossum
- Benjamin Dulau (dbenjamin)
- Mathieu Lemoine (lemoinem)
+ - Thomas Calvet (fancyweb)
- Christian Schmidt
- Andreas Hucks (meandmymonkey)
- Noel Guilbert (noel)
@@ -200,6 +201,7 @@ Symfony is the result of the work of many people who made the code better
- bronze1man
- sun (sun)
- Larry Garfield (crell)
+ - Michaël Perrin (michael.perrin)
- Martin Schuhfuß (usefulthink)
- apetitpa
- Matthieu Bontemps (mbontemps)
@@ -221,7 +223,6 @@ Symfony is the result of the work of many people who made the code better
- Tom Van Looy (tvlooy)
- Sven Paulus (subsven)
- Yanick Witschi (toflar)
- - Thomas Calvet (fancyweb)
- Rui Marinho (ruimarinho)
- Alessandro Chitolina
- Eugene Wissner
@@ -230,7 +231,6 @@ Symfony is the result of the work of many people who made the code better
- Leo Feyer
- Tristan Darricau (nicofuma)
- Nikolay Labinskiy (e-moe)
- - Michaël Perrin (michael.perrin)
- Marcel Beerta (mazen)
- Albert Casademont (acasademont)
- Loïc Faugeron
@@ -253,6 +253,7 @@ Symfony is the result of the work of many people who made the code better
- Ruben Gonzalez (rubenrua)
- Adam Prager (padam87)
- Benoît Burnichon (bburnichon)
+ - Florent Mata (fmata)
- Roman Marintšenko (inori)
- Xavier Montaña Carreras (xmontana)
- Mickaël Andrieu (mickaelandrieu)
@@ -284,6 +285,7 @@ Symfony is the result of the work of many people who made the code better
- Andreas Schempp (aschempp)
- jdhoek
- Pavel Batanov (scaytrase)
+ - Massimiliano Arione (garak)
- Bob den Otter (bopp)
- Nikita Konstantinov
- Wodor Wodorski
@@ -296,7 +298,6 @@ Symfony is the result of the work of many people who made the code better
- Roumen Damianoff (roumen)
- Antonio J. García Lagar (ajgarlag)
- Kim Hemsø Rasmussen (kimhemsoe)
- - Florent Mata (fmata)
- Wouter Van Hecke
- Jérôme Parmentier (lctrs)
- Michael Babker (mbabker)
@@ -309,6 +310,7 @@ Symfony is the result of the work of many people who made the code better
- Chad Sikorra (chadsikorra)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
+ - Gary PEGEOT (gary-p)
- Manuel Kiessling (manuelkiessling)
- Atsuhiro KUBO (iteman)
- Andrew Moore (finewolf)
@@ -332,7 +334,6 @@ Symfony is the result of the work of many people who made the code better
- Adrian Rudnik (kreischweide)
- Francesc Rosàs (frosas)
- Romain Pierre (romain-pierre)
- - Massimiliano Arione (garak)
- Julien Galenski (ruian)
- Bongiraud Dominique
- janschoenherr
@@ -343,6 +344,7 @@ Symfony is the result of the work of many people who made the code better
- Thierry Thuon (lepiaf)
- Ricard Clau (ricardclau)
- Mark Challoner (markchalloner)
+ - Colin O'Dell (colinodell)
- Gennady Telegin (gtelegin)
- Ben Davies (bendavies)
- Erin Millard
@@ -380,7 +382,7 @@ Symfony is the result of the work of many people who made the code better
- Grzegorz (Greg) Zdanowski (kiler129)
- Kirill chEbba Chebunin (chebba)
- Greg Thornton (xdissent)
- - Gary PEGEOT (gary-p)
+ - Sullivan SENECHAL (soullivaneuh)
- Costin Bereveanu (schniper)
- Loïc Chardonnet (gnusat)
- Marek Kalnik (marekkalnik)
@@ -407,6 +409,7 @@ Symfony is the result of the work of many people who made the code better
- Karoly Negyesi (chx)
- Ivan Kurnosov
- Xavier HAUSHERR
+ - David Prévot
- Albert Jessurum (ajessu)
- Laszlo Korte
- Miha Vrhovnik
@@ -431,13 +434,13 @@ Symfony is the result of the work of many people who made the code better
- Christopher Davis (chrisguitarguy)
- Jan Schumann
- Niklas Fiekas
- - Colin O'Dell (colinodell)
- Markus Bachmann (baachi)
- lancergr
- Zan Baldwin
- Mihai Stancu
- Olivier Dolbeau (odolbeau)
- Jan Rosier (rosier)
+ - Alessandro Lai (jean85)
- Arturs Vonda
- Josip Kruslin
- Asmir Mustafic (goetas)
@@ -484,7 +487,6 @@ Symfony is the result of the work of many people who made the code better
- Haralan Dobrev (hkdobrev)
- Sebastian Bergmann
- Miroslav Sustek
- - Sullivan SENECHAL (soullivaneuh)
- Pablo Díez (pablodip)
- Martin Hujer (martinhujer)
- Kevin McBride
@@ -508,6 +510,7 @@ Symfony is the result of the work of many people who made the code better
- Markus Lanthaler (lanthaler)
- Remi Collet
- Vicent Soria Durá (vicentgodella)
+ - Michael Moravec
- Anthony Ferrara
- Ioan Negulescu
- Jakub Škvára (jskvara)
@@ -565,7 +568,6 @@ Symfony is the result of the work of many people who made the code better
- Disquedur
- Michiel Boeckaert (milio)
- Geoffrey Tran (geoff)
- - David Prévot
- Jan Behrens
- Mantas Var (mvar)
- Sebastian Krebs
@@ -584,7 +586,6 @@ Symfony is the result of the work of many people who made the code better
- Max Rath (drak3)
- Stéphane Escandell (sescandell)
- Konstantin S. M. Möllers (ksmmoellers)
- - Alessandro Lai (jean85)
- James Johnston
- Sinan Eldem
- Alexandre Dupuy (satchette)
@@ -652,6 +653,7 @@ Symfony is the result of the work of many people who made the code better
- Szijarto Tamas
- Robin Lehrmann (robinlehrmann)
- Catalin Dan
+ - Jaroslav Kuba
- Stephan Vock
- Benjamin Zikarsky (bzikarsky)
- Simon Schick (simonsimcity)
@@ -713,6 +715,7 @@ Symfony is the result of the work of many people who made the code better
- Yuen-Chi Lian
- Besnik Br
- Jose Gonzalez
+ - Oleksii Zhurbytskyi
- Dariusz Ruminski
- Joshua Nye
- Claudio Zizza
@@ -737,7 +740,6 @@ Symfony is the result of the work of many people who made the code better
- Marc Morera (mmoreram)
- Saif Eddin Gmati (azjezz)
- Smaine Milianni (ismail1432)
- - Michael Moravec
- Andrew Hilobok (hilobok)
- Noah Heck (myesain)
- Christian Soronellas (theunic)
@@ -787,6 +789,7 @@ Symfony is the result of the work of many people who made the code better
- Sofiane HADDAG (sofhad)
- frost-nzcr4
- Bozhidar Hristov
+ - Ivan Nikolaev (destillat)
- andrey1s
- Abhoryo
- Fabian Vogler (fabian)
@@ -882,6 +885,7 @@ Symfony is the result of the work of many people who made the code better
- datibbaw
- Erik Saunier (snickers)
- Rootie
+ - Kyle
- Raul Fraile (raulfraile)
- sensio
- Sebastien Morel (plopix)
@@ -911,6 +915,7 @@ Symfony is the result of the work of many people who made the code better
- Michael Tibben
- Billie Thompson
- Sander Marechal
+ - ProgMiner
- Oleg Golovakhin (doc_tr)
- Icode4Food (icode4food)
- Radosław Benkel
@@ -999,6 +1004,7 @@ Symfony is the result of the work of many people who made the code better
- Denis Kop
- Jean-Guilhem Rouel (jean-gui)
- jfcixmedia
+ - Dominic Tubach
- Nikita Konstantinov
- Martijn Evers
- Benjamin Paap (benjaminpaap)
@@ -1041,6 +1047,7 @@ Symfony is the result of the work of many people who made the code better
- Alexander Cheprasov
- Rodrigo Díez Villamuera (rodrigodiez)
- e-ivanov
+ - Einenlum
- Jochen Bayer (jocl)
- Alex Bowers
- Jeremy Bush
@@ -1060,7 +1067,6 @@ Symfony is the result of the work of many people who made the code better
- David Otton
- Will Donohoe
- peter
- - Jaroslav Kuba
- Jérémy Jourdin (jjk801)
- BRAMILLE Sébastien (oktapodia)
- Artem Kolesnikov (tyomo4ka)
@@ -1166,6 +1172,7 @@ Symfony is the result of the work of many people who made the code better
- Saem Ghani
- Clément LEFEBVRE
- Conrad Kleinespel
+ - Zacharias Luiten
- Sebastian Utz
- Adrien Gallou (agallou)
- Maks Rafalko (bornfree)
@@ -1231,6 +1238,7 @@ Symfony is the result of the work of many people who made the code better
- WedgeSama
- Felds Liscia
- Chihiro Adachi (chihiro-adachi)
+ - Emanuele Panzeri (thepanz)
- Tadcka
- Beth Binkovitz
- Gonzalo Míguez
@@ -1303,6 +1311,7 @@ Symfony is the result of the work of many people who made the code better
- Benjamin Bender
- Jared Farrish
- karl.rixon
+ - raplider
- Konrad Mohrfeldt
- Lance Chen
- Ciaran McNulty (ciaranmcnulty)
@@ -1371,18 +1380,20 @@ Symfony is the result of the work of many people who made the code better
- Harold Iedema
- Arnau González (arnaugm)
- Simon Bouland (bouland)
- - Ivan Nikolaev (destillat)
- Matthew Foster (mfoster)
- Paul Seiffert (seiffert)
- Vasily Khayrulin (sirian)
- Stefan Koopmanschap (skoop)
- Stefan Hüsges (tronsha)
+ - Vlad Gregurco (vgregurco)
- Jake Bishop (yakobeyak)
- Dan Blows
- Matt Wells
- Nicolas Appriou
- stloyd
+ - Andreas
- Chris Tickner
+ - BoShurik
- Andrew Coulton
- Jeremy Benoist
- Michal Gebauer
@@ -1396,7 +1407,9 @@ Symfony is the result of the work of many people who made the code better
- Luis Muñoz
- Matthew Donadio
- Houziaux mike
+ - Phobetor
- Andreas
+ - Markus
- Thomas Chmielowiec
- shdev
- Andrey Ryaguzov
@@ -1404,6 +1417,7 @@ Symfony is the result of the work of many people who made the code better
- Peter Bex
- Manatsawin Hanmongkolchai
- Gunther Konig
+ - Mickael GOETZ
- Maciej Schmidt
- Greg ORIOL
- Dennis Væversted
@@ -1415,6 +1429,7 @@ Symfony is the result of the work of many people who made the code better
- Mike Francis
- Christoph Nissle (derstoffel)
- Ionel Scutelnicu (ionelscutelnicu)
+ - Grenier Kévin (mcsky_biig)
- Nicolas Tallefourtané (nicolab)
- Botond Dani (picur)
- Thierry Marianne (thierrymarianne)
@@ -1432,7 +1447,6 @@ Symfony is the result of the work of many people who made the code better
- Nicolas Bastien (nicolas_bastien)
- Denis (yethee)
- Andrew Zhilin (zhil)
- - Oleksii Zhurbytskyi
- Andy Stanberry
- Felix Marezki
- Normunds
@@ -1813,6 +1827,7 @@ Symfony is the result of the work of many people who made the code better
- jspee
- David Soria Parra
- Sergiy Sokolenko
+ - Ahmed Abdulrahman
- dinitrol
- Penny Leach
- Yurii K
@@ -1973,7 +1988,6 @@ Symfony is the result of the work of many people who made the code better
- fh-github@fholzhauer.de
- AbdElKader Bouadjadja
- DSeemiller
- - Kyle
- Jan Emrich
- Mark Topper
- Xavier REN
@@ -2001,3 +2015,4 @@ Symfony is the result of the work of many people who made the code better
- Matej Žilák (teo_sk)
- Vladislav Vlastovskiy (vlastv)
- RENAUDIN Xavier (xorrox)
+ - Yannick Vanhaeren (yvh)
diff --git a/appveyor.yml b/appveyor.yml
index bd35af195d13e..45373a93583f9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -10,6 +10,7 @@ init:
- SET PATH=c:\php;%PATH%
- SET COMPOSER_NO_INTERACTION=1
- SET SYMFONY_DEPRECATIONS_HELPER=strict
+ - SET "SYMFONY_REQUIRE=>=3.4"
- SET ANSICON=121x90 (121x90)
- SET SYMFONY_PHPUNIT_VERSION=4.8
- REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f
@@ -48,9 +49,10 @@ install:
- copy /Y php.ini-min php.ini
- echo extension=php_openssl.dll >> php.ini
- cd c:\projects\symfony
- - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.3.0/composer.phar)
+ - IF NOT EXIST composer.phar (appveyor DownloadFile https://github.com/composer/composer/releases/download/1.7.1/composer.phar)
- php composer.phar self-update
- copy /Y .composer\* %APPDATA%\Composer\
+ - php composer.phar global require --no-progress --no-scripts --no-plugins symfony/flex dev-master
- php .github/build-packages.php "HEAD^" src\Symfony\Bridge\PhpUnit
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
- php composer.phar config platform.php 5.5.9
diff --git a/composer.json b/composer.json
index e0a1c53c4f158..6d5065d4d3084 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
"require": {
"php": "^5.5.9|>=7.0.8",
"ext-xml": "*",
- "doctrine/common": "~2.4@stable",
+ "doctrine/common": "~2.4",
"fig/link-util": "^1.0",
"twig/twig": "^1.35|^2.4.4",
"psr/cache": "~1.0",
@@ -92,7 +92,7 @@
"doctrine/cache": "~1.6",
"doctrine/data-fixtures": "1.0.*",
"doctrine/dbal": "~2.4",
- "doctrine/orm": "~2.4,>=2.4.5,<=2.7.0",
+ "doctrine/orm": "~2.4,>=2.4.5",
"doctrine/doctrine-bundle": "~1.4",
"monolog/monolog": "~1.11",
"ocramius/proxy-manager": "~0.4|~1.0|~2.0",
diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
index a26ce98107f60..d8b55eb808fc2 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
@@ -482,7 +482,7 @@ public function testAssociatedEntity()
$this->buildViolation('myMessage')
->atPath('property.path.single')
- ->setParameter('{{ value }}', 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity") identified by (id => 1)')
+ ->setParameter('{{ value }}', 'foo')
->setInvalidValue($entity1)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->setCause(array($associated, $associated2))
diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
index 2015e7fb3acc6..161a187ff98ab 100644
--- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
+++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
@@ -186,6 +186,10 @@ private function formatWithIdentifiers(ObjectManager $em, ClassMetadata $class,
return $this->formatValue($value, self::PRETTY_DATE);
}
+ if (\method_exists($value, '__toString')) {
+ return (string) $value;
+ }
+
if ($class->getName() !== $idClass = \get_class($value)) {
// non unique value might be a composite PK that consists of other entity objects
if ($em->getMetadataFactory()->hasMetadataFor($idClass)) {
diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json
index 1535f8f42b8f8..420535b7516fd 100644
--- a/src/Symfony/Bridge/Doctrine/composer.json
+++ b/src/Symfony/Bridge/Doctrine/composer.json
@@ -17,7 +17,7 @@
],
"require": {
"php": "^5.5.9|>=7.0.8",
- "doctrine/common": "~2.4@stable",
+ "doctrine/common": "~2.4",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.0"
},
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php
index ce8f62d2c53c0..6674feb94a88e 100644
--- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php
+++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php
@@ -16,7 +16,7 @@ public function test()
$this->markTestSkipped('This test cannot be run on HHVM.');
}
- exec('type phpdbg', $output, $returnCode);
+ exec('type phpdbg 2> /dev/null', $output, $returnCode);
if (\PHP_VERSION_ID >= 70000 && 0 === $returnCode) {
$php = 'phpdbg -qrr';
diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
index 197650915fe91..bcfc432f8a139 100755
--- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
+++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
@@ -101,7 +101,8 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
}
$prevRoot = getenv('COMPOSER_ROOT_VERSION');
putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99");
- $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-suggest --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true)));
+ // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS
+ $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true)));
putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : ''));
if ($exit) {
exit($exit);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php
index ddea9dc1742fe..a3f73cfc35fa7 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php
@@ -49,4 +49,14 @@ public function testCsrfTokensAreClearedOnLogout()
$this->assertFalse(static::$kernel->getContainer()->get('test.security.csrf.token_storage')->hasToken('foo'));
}
+
+ public function testAccessControlDoesNotApplyOnLogout()
+ {
+ $client = $this->createClient(array('test_case' => 'LogoutAccess', 'root_config' => 'config.yml'));
+
+ $client->request('POST', '/login', array('_username' => 'johannes', '_password' => 'test'));
+ $client->request('GET', '/logout');
+
+ $this->assertRedirect($client->getResponse(), '/');
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/bundles.php
new file mode 100644
index 0000000000000..c934b52aee7c0
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/bundles.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
+use Symfony\Bundle\SecurityBundle\SecurityBundle;
+
+return array(
+ new FrameworkBundle(),
+ new SecurityBundle(),
+);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/config.yml
new file mode 100644
index 0000000000000..2e20735b80236
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/config.yml
@@ -0,0 +1,26 @@
+imports:
+- { resource: ./../config/framework.yml }
+
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ providers:
+ in_memory:
+ memory:
+ users:
+ johannes: { password: test, roles: [ROLE_USER] }
+
+ firewalls:
+ default:
+ form_login:
+ check_path: login
+ remember_me: true
+ require_previous_session: false
+ logout: ~
+ anonymous: ~
+ stateless: true
+
+ access_control:
+ - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
+ - { path: .*, roles: IS_AUTHENTICATED_FULLY }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/routing.yml
new file mode 100644
index 0000000000000..1dddfca2f8154
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutAccess/routing.yml
@@ -0,0 +1,5 @@
+login:
+ path: /login
+
+logout:
+ path: /logout
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index fa304be517a22..57d313d87142c 100644
--- a/src/Symfony/Bundle/SecurityBundle/composer.json
+++ b/src/Symfony/Bundle/SecurityBundle/composer.json
@@ -18,7 +18,7 @@
"require": {
"php": "^5.5.9|>=7.0.8",
"ext-xml": "*",
- "symfony/security": "~3.4.12|~4.0.12|^4.1.1",
+ "symfony/security": "~3.4.15|~4.0.15|^4.1.4",
"symfony/dependency-injection": "^3.4.3|^4.0.3",
"symfony/http-kernel": "~3.4|~4.0",
"symfony/polyfill-php70": "~1.0"
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php
index 76e0608006173..d1f87903406fe 100644
--- a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php
+++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php
@@ -89,6 +89,7 @@ public function testDefaultOptions()
$this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION));
$this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL));
+ $this->assertSame(1, $client->getOption(\Memcached::OPT_TCP_NODELAY));
$this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE));
}
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisClusterAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisClusterAdapterTest.php
new file mode 100644
index 0000000000000..852079c00ce79
--- /dev/null
+++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisClusterAdapterTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Tests\Adapter;
+
+class RedisClusterAdapterTest extends AbstractRedisAdapterTest
+{
+ public static function setupBeforeClass()
+ {
+ if (!class_exists('RedisCluster')) {
+ self::markTestSkipped('The RedisCluster class is required.');
+ }
+ if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) {
+ self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.');
+ }
+
+ self::$redis = new \RedisCluster(null, explode(' ', $hosts));
+ }
+}
diff --git a/src/Symfony/Component/Cache/Tests/Simple/RedisClusterCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/RedisClusterCacheTest.php
new file mode 100644
index 0000000000000..99d4e518fb409
--- /dev/null
+++ b/src/Symfony/Component/Cache/Tests/Simple/RedisClusterCacheTest.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Tests\Simple;
+
+class RedisClusterCacheTest extends AbstractRedisCacheTest
+{
+ public static function setupBeforeClass()
+ {
+ if (!class_exists('RedisCluster')) {
+ self::markTestSkipped('The RedisCluster class is required.');
+ }
+ if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) {
+ self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.');
+ }
+
+ self::$redis = new \RedisCluster(null, explode(' ', $hosts));
+ }
+}
diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
index 7e36164293842..5983d9ebd1da5 100644
--- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
+++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php
@@ -134,6 +134,7 @@ public static function createConnection($servers, array $options = array())
$options = array_change_key_case($options, CASE_UPPER);
$client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
$client->setOption(\Memcached::OPT_NO_BLOCK, true);
+ $client->setOption(\Memcached::OPT_TCP_NODELAY, true);
if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) {
$client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
}
diff --git a/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt b/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt
index 74cf2e9171001..7211afbdf85ea 100644
--- a/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt
+++ b/src/Symfony/Component/Debug/Tests/phpt/decorate_exception_hander.phpt
@@ -38,8 +38,7 @@ Did you forget a "use" statement for another namespace?"
["line":protected]=>
int(%d)
["trace":"Exception":private]=>
- array(0) {
- }
+ array(%d) {%A}
["previous":"Exception":private]=>
NULL
["severity":protected]=>
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php
index 19f01b8536cb4..aeebbf0bf18c4 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php
@@ -34,15 +34,17 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
private $graph;
private $currentDefinition;
private $onlyConstructorArguments;
+ private $hasProxyDumper;
private $lazy;
private $expressionLanguage;
/**
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
*/
- public function __construct($onlyConstructorArguments = false)
+ public function __construct($onlyConstructorArguments = false, $hasProxyDumper = true)
{
$this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
+ $this->hasProxyDumper = (bool) $hasProxyDumper;
}
/**
@@ -97,7 +99,7 @@ protected function processValue($value, $isRoot = false)
$targetId,
$targetDefinition,
$value,
- $this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
+ $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
);
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
index 8ffb245c12f2c..839af1ae232d3 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
@@ -66,7 +66,7 @@ private function getDefinitionId($id, ContainerBuilder $container)
$seen = array();
while ($container->hasAlias($id)) {
if (isset($seen[$id])) {
- throw new ServiceCircularReferenceException($id, array_keys($seen));
+ throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), array($id)));
}
$seen[$id] = true;
$id = $container->normalizeId($container->getAlias($id));
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
index 5dfa1da59dc50..4d3e3883d428a 100644
--- a/src/Symfony/Component/DependencyInjection/Container.php
+++ b/src/Symfony/Component/DependencyInjection/Container.php
@@ -294,7 +294,7 @@ public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERE
}
if (isset($this->loading[$id])) {
- throw new ServiceCircularReferenceException($id, array_keys($this->loading));
+ throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), array($id)));
}
$this->loading[$id] = true;
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index c2b73e70c84dc..7a66382f6058b 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -122,7 +122,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private $autoconfiguredInstanceof = array();
private $removedIds = array();
- private $alreadyLoading = array();
private static $internalTypes = array(
'int' => true,
@@ -588,22 +587,32 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
return $this->doGet($id, $invalidBehavior);
}
- private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = array())
+ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, $isConstructorArgument = false)
{
$id = $this->normalizeId($id);
if (isset($inlineServices[$id])) {
return $inlineServices[$id];
}
- if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
- return parent::get($id, $invalidBehavior);
+ if (null === $inlineServices) {
+ $isConstructorArgument = true;
+ $inlineServices = array();
}
- if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
- return $service;
+ try {
+ if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
+ return parent::get($id, $invalidBehavior);
+ }
+ if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
+ return $service;
+ }
+ } catch (ServiceCircularReferenceException $e) {
+ if ($isConstructorArgument) {
+ throw $e;
+ }
}
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
- return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices);
+ return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
}
try {
@@ -616,16 +625,17 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
throw $e;
}
- $loading = isset($this->alreadyLoading[$id]) ? 'loading' : 'alreadyLoading';
- $this->{$loading}[$id] = true;
+ if ($isConstructorArgument) {
+ $this->loading[$id] = true;
+ }
try {
- $service = $this->createService($definition, $inlineServices, $id);
+ return $this->createService($definition, $inlineServices, $isConstructorArgument, $id);
} finally {
- unset($this->{$loading}[$id]);
+ if ($isConstructorArgument) {
+ unset($this->loading[$id]);
+ }
}
-
- return $service;
}
/**
@@ -1092,7 +1102,7 @@ public function findDefinition($id)
* @throws RuntimeException When the service is a synthetic service
* @throws InvalidArgumentException When configure callable is not callable
*/
- private function createService(Definition $definition, array &$inlineServices, $id = null, $tryProxy = true)
+ private function createService(Definition $definition, array &$inlineServices, $isConstructorArgument = false, $id = null, $tryProxy = true)
{
if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
return $inlineServices[$h];
@@ -1110,16 +1120,14 @@ private function createService(Definition $definition, array &$inlineServices, $
@trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
}
- if ($tryProxy && $definition->isLazy()) {
- $proxy = $this
- ->getProxyInstantiator()
- ->instantiateProxy(
- $this,
- $definition,
- $id, function () use ($definition, &$inlineServices, $id) {
- return $this->createService($definition, $inlineServices, $id, false);
- }
- );
+ if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) {
+ $proxy = $proxy->instantiateProxy(
+ $this,
+ $definition,
+ $id, function () use ($definition, &$inlineServices, $id) {
+ return $this->createService($definition, $inlineServices, true, $id, false);
+ }
+ );
$this->shareService($definition, $proxy, $id, $inlineServices);
return $proxy;
@@ -1131,19 +1139,21 @@ private function createService(Definition $definition, array &$inlineServices, $
require_once $parameterBag->resolveValue($definition->getFile());
}
- $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices);
-
- if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
- return $this->services[$id];
- }
+ $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument);
if (null !== $factory = $definition->getFactory()) {
if (\is_array($factory)) {
- $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices), $factory[1]);
+ $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]);
} elseif (!\is_string($factory)) {
throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
}
+ }
+ if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
+ return $this->services[$id];
+ }
+
+ if (null !== $factory) {
$service = \call_user_func_array($factory, $arguments);
if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
@@ -1214,11 +1224,11 @@ public function resolveServices($value)
return $this->doResolveServices($value);
}
- private function doResolveServices($value, array &$inlineServices = array())
+ private function doResolveServices($value, array &$inlineServices = array(), $isConstructorArgument = false)
{
if (\is_array($value)) {
foreach ($value as $k => $v) {
- $value[$k] = $this->doResolveServices($v, $inlineServices);
+ $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument);
}
} elseif ($value instanceof ServiceClosureArgument) {
$reference = $value->getValues()[0];
@@ -1261,9 +1271,9 @@ private function doResolveServices($value, array &$inlineServices = array())
return $count;
});
} elseif ($value instanceof Reference) {
- $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices);
+ $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument);
} elseif ($value instanceof Definition) {
- $value = $this->createService($value, $inlineServices);
+ $value = $this->createService($value, $inlineServices, $isConstructorArgument);
} elseif ($value instanceof Parameter) {
$value = $this->getParameter((string) $value);
} elseif ($value instanceof Expression) {
@@ -1584,20 +1594,6 @@ protected function getEnv($name)
}
}
- /**
- * Retrieves the currently set proxy instantiator or instantiates one.
- *
- * @return InstantiatorInterface
- */
- private function getProxyInstantiator()
- {
- if (!$this->proxyInstantiator) {
- $this->proxyInstantiator = new RealServiceInstantiator();
- }
-
- return $this->proxyInstantiator;
- }
-
private function callMethod($service, $call, array &$inlineServices)
{
foreach (self::getServiceConditionals($call[1]) as $s) {
@@ -1627,7 +1623,7 @@ private function shareService(Definition $definition, $service, $id, array &$inl
if (null !== $id && $definition->isShared()) {
$this->services[$id] = $service;
- unset($this->loading[$id], $this->alreadyLoading[$id]);
+ unset($this->loading[$id]);
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 71e776310b270..5530912c90a9e 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -15,6 +15,7 @@
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
+use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -138,7 +139,20 @@ public function dump(array $options = array())
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
- (new AnalyzeServiceReferencesPass())->process($this->container);
+ if ($this->getProxyDumper() instanceof NullDumper) {
+ (new AnalyzeServiceReferencesPass(true, false))->process($this->container);
+ try {
+ (new CheckCircularReferencesPass())->process($this->container);
+ } catch (ServiceCircularReferenceException $e) {
+ $path = $e->getPath();
+ end($path);
+ $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge';
+
+ throw new ServiceCircularReferenceException($e->getServiceId(), $path);
+ }
+ }
+
+ (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
$this->circularReferences = array();
$checkedNodes = array();
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
@@ -286,21 +300,18 @@ private function getProxyDumper()
*
* @return string
*/
- private function addServiceLocalTempVariables($cId, Definition $definition, \SplObjectStorage $inlinedDefinitions, \SplObjectStorage $allInlinedDefinitions)
+ private function addServiceLocalTempVariables($cId, Definition $definition, \SplObjectStorage $inlinedDefinitions, array $serviceCalls, $preInstance = false)
{
- $allCalls = $calls = $behavior = array();
+ $calls = array();
- foreach ($allInlinedDefinitions as $def) {
- $arguments = array($def->getArguments(), $def->getFactory(), $def->getProperties(), $def->getMethodCalls(), $def->getConfigurator());
- $this->getServiceCallsFromArguments($arguments, $allCalls, false, $cId, $behavior, $allInlinedDefinitions[$def]);
- }
-
- $isPreInstance = isset($inlinedDefinitions[$definition]) && isset($this->circularReferences[$cId]) && !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
foreach ($inlinedDefinitions as $def) {
- $this->getServiceCallsFromArguments(array($def->getArguments(), $def->getFactory()), $calls, $isPreInstance, $cId);
+ if ($preInstance && !$inlinedDefinitions[$def][1]) {
+ continue;
+ }
+ $this->getServiceCallsFromArguments(array($def->getArguments(), $def->getFactory()), $calls, $preInstance, $cId);
if ($def !== $definition) {
$arguments = array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator());
- $this->getServiceCallsFromArguments($arguments, $calls, $isPreInstance && !$this->hasReference($cId, $arguments, true), $cId);
+ $this->getServiceCallsFromArguments($arguments, $calls, $preInstance && !$this->hasReference($cId, $arguments, true), $cId);
}
}
if (!isset($inlinedDefinitions[$definition])) {
@@ -309,23 +320,23 @@ private function addServiceLocalTempVariables($cId, Definition $definition, \Spl
}
$code = '';
- foreach ($calls as $id => $callCount) {
+ foreach ($calls as $id => list($callCount)) {
if ('service_container' === $id || $id === $cId || isset($this->referenceVariables[$id])) {
continue;
}
- if ($callCount <= 1 && $allCalls[$id] <= 1) {
+ if ($callCount <= 1 && $serviceCalls[$id][0] <= 1) {
continue;
}
$name = $this->getNextVariableName();
$this->referenceVariables[$id] = new Variable($name);
- $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id] ? new Reference($id, $behavior[$id]) : null;
+ $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $serviceCalls[$id][1] ? new Reference($id, $serviceCalls[$id][1]) : null;
$code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($id, $reference));
}
if ('' !== $code) {
- if ($isPreInstance) {
+ if ($preInstance) {
$code .= <<
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 284af1f9f932b..36c9f1d913702 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -549,11 +549,6 @@ private function getCurrentLineIndentation() private function getNextEmbedBlock($indentation = null, $inSequence = false) { $oldLineIndentation = $this->getCurrentLineIndentation(); - $blockScalarIndentations = array(); - - if ($this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $oldLineIndentation; - } if (!$this->moveToNextLine()) { return; @@ -612,30 +607,9 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); - if (empty($blockScalarIndentations) && $this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $this->getCurrentLineIndentation(); - } - - $previousLineIndentation = $this->getCurrentLineIndentation(); - while ($this->moveToNextLine()) { $indent = $this->getCurrentLineIndentation(); - // terminate all block scalars that are more indented than the current line - if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && '' !== trim($this->currentLine)) { - foreach ($blockScalarIndentations as $key => $blockScalarIndentation) { - if ($blockScalarIndentation >= $indent) { - unset($blockScalarIndentations[$key]); - } - } - } - - if (empty($blockScalarIndentations) && !$this->isCurrentLineComment() && $this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $indent; - } - - $previousLineIndentation = $indent; - if ($isItUnindentedCollection && !$this->isCurrentLineEmpty() && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) { $this->moveToPreviousLine(); break; @@ -1054,16 +1028,6 @@ private function isStringUnIndentedCollectionItem() return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- '); } - /** - * Tests whether or not the current line is the header of a block scalar. - * - * @return bool - */ - private function isBlockScalarHeader() - { - return (bool) self::preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); - } - /** * A local wrapper for `preg_match` which will throw a ParseException if there * is an internal error in the PCRE engine.