Merge branch '3.3' into 3.4

* 3.3: (31 commits)
  Using FQ name for PHP_VERSION_ID
  [EventDispatcher] Handle laziness internally instead of relying on ClosureProxyArgument
  Fix CacheCollectorPass priority
  [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323
  [Routing] Allow GET requests to be redirected. Fixes #23004
  [DI] Deal with inlined non-shared services
  [Cache] Ignore missing annotations.php
  [DI] Autowiring exception thrown when inlined service is removed
  Improving deprecation message when hitting the "deprecated type" lookup, but an alias is available
  Harden the debugging of Twig filters and functions
  Fixing a bug where an autowiring exception was thrown even when that service was removed
  Remove extra arg in call to TraceableAdapter::start()
  Support unknown compiler log format
  [Config] Allow empty globs
  Fix decorating TagAware adapters in dev
  [Profiler] Fix clicking on links inside toggle
  [Profiler] Fix text selection on exception pages
  bumped Symfony version to 3.3.1
  updated VERSION for 3.3.0
  updated CHANGELOG for 3.3.0
  ...
This commit is contained in:
Fabien Potencier 2017-06-01 14:02:15 -07:00
commit 69f1578d8c
59 changed files with 1153 additions and 152 deletions

View File

@ -11,7 +11,7 @@ array_shift($dirs);
$mergeBase = trim(shell_exec(sprintf('git merge-base %s HEAD', array_shift($dirs))));
$packages = array();
$flags = PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0;
$flags = \PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0;
foreach ($dirs as $k => $dir) {
if (!system("git diff --name-only $mergeBase -- $dir", $exitStatus)) {

View File

@ -7,6 +7,29 @@ in 3.2 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.2.0...v3.2.1
* 3.2.9 (2017-05-29)
* bug #22847 [Console] ChoiceQuestion must have choices (ro0NL)
* bug #22900 [FrameworkBundle][Console] Fix the override of a command registered by the kernel (aaa2000)
* bug #22910 [Filesystem] improve error handling in lock() (xabbuh)
* bug #22924 [Cache] Dont use pipelining with RedisCluster (nicolas-grekas)
* bug #22718 [Console] Fixed different behaviour of key and value user inputs in multiple choice question (borNfreee)
* bug #22829 [Yaml] fix colon without space deprecation (xabbuh)
* bug #22901 Fix missing abstract key in XmlDumper (weaverryan)
* bug #22912 [DI] Avoid private call to Container::has() (ro0NL)
* bug #22866 [DI] Check for privates before shared services (ro0NL)
* bug #22874 [WebProfilerBundle] Fix sub-requests display in time profiler panel (nicolas-grekas)
* bug #22817 [PhpUnitBridge] optional error handler arguments (xabbuh)
* bug #22752 Improved how profiler errors are displayed on small screens (javiereguiluz)
* bug #22715 [FrameworkBundle] remove Security deps from the require section (xabbuh)
* bug #22647 [VarDumper] Fix dumping of non-nested stubs (nicolas-grekas)
* bug #22409 [Yaml] respect inline level when dumping objects as maps (goetas, xabbuh)
* bug #22584 [Security] Avoid unnecessary route lookup for empty logout path (ro0NL)
* bug #22690 [Console] Fix errors not rethrown even if not handled by console.error listeners (chalasr)
* bug #22669 [FrameworkBundle] AbstractConfigCommand: do not try registering bundles twice (ogizanagi)
* bug #22676 [FrameworkBundle] Adding the extension XML (flug)
* bug #22652 [Workflow] Move twig extension registration to twig bundle (ogizanagi)
* 3.2.8 (2017-05-01)
* bug #22550 Allow Upper Case property names in ObjectNormalizer (insekticid)

View File

@ -7,6 +7,45 @@ in 3.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/v3.3.0...v3.3.1
* 3.3.0 (2017-05-29)
* bug #22940 [Config] Fallback to regular import when glob fails (nicolas-grekas)
* bug #22847 [Console] ChoiceQuestion must have choices (ro0NL)
* bug #22900 [FrameworkBundle][Console] Fix the override of a command registered by the kernel (aaa2000)
* bug #22930 Revert "bug #22925 [PhpUnitBridge] Adjust PHPUnit class_alias check (nicolas-grekas)
* bug #22910 [Filesystem] improve error handling in lock() (xabbuh)
* bug #22924 [Cache] Dont use pipelining with RedisCluster (nicolas-grekas)
* bug #22928 [WebProfilerBundle] Fixed options stub values display in form profiler (HeahDude)
* feature #22838 Make the simple exception pages match the new style (javiereguiluz)
* bug #22925 [PhpUnitBridge] Adjust PHPUnit class_alias check to also check for namespaced class (GawainLynch)
* bug #22718 [Console] Fixed different behaviour of key and value user inputs in multiple choice question (borNfreee)
* bug #22921 [FrameworkBundle] Only override getProjectDir if it exists in the kernel (aschempp)
* feature #22905 [FrameworkBundle][Validator] Move the PSR-11 factory to the component (ogizanagi)
* bug #22728 [HttpKernel] Fix kernel.project_dir extensibility (chalasr)
* bug #22829 [Yaml] fix colon without space deprecation (xabbuh)
* bug #22901 Fix missing abstract key in XmlDumper (weaverryan)
* bug #22912 [DI] Avoid private call to Container::has() (ro0NL)
* feature #22904 [HttpFoundation] Add Request::HEADER_X_FORWARDED_AWS_ELB const (nicolas-grekas)
* bug #22878 [Yaml] parse PHP constants in mapping keys (xabbuh)
* bug #22873 [HttpKernel] don't call getTrustedHeaderName() if possible (xabbuh)
* feature #22892 [ProxyManager] Add FC layer (nicolas-grekas)
* bug #22866 [DI] Check for privates before shared services (ro0NL)
* feature #22884 [DI] Add missing deprecation on Extension::getClassesToCompile (nicolas-grekas)
* bug #22874 [WebProfilerBundle] Fix sub-requests display in time profiler panel (nicolas-grekas)
* bug #22853 [Yaml] fix multiline block handling (xabbuh)
* bug #22872 [FrameworkBundle] Handle project dir in cache:clear command (nicolas-grekas)
* feature #22808 [FrameworkBundle][Validator] Deprecate passing validator instances/aliases over using the service locator (ogizanagi)
* bug #22857 [DI] Fix autowire error for inlined services (weaverryan)
* bug #22858 [SecurityBundle] Prevent auto-registration of UserPasswordEncoderCommand (chalasr)
* bug #22859 [Profiler][VarDumper] Fix searchbar css when in toolbar (ogizanagi)
* bug #22614 [Process] Fixed escaping arguments on Windows when inheritEnvironmentVariables is set to false (maryo)
* bug #22817 [PhpUnitBridge] optional error handler arguments (xabbuh)
* bug #22781 [DI][Serializer] Fix missing de(normalizer|coder) autoconfig (ogizanagi)
* bug #22790 [DependencyInjection] Fix dumping of RewindableGenerator with empty IteratorArgument (meyerbaptiste)
* bug #22787 [MonologBridge] Fix the Monlog ServerLogHandler from Hanging on Windows (ChadSikorra)
* bug #22768 Use 0.0.0.0 as the server log command host default. (ChadSikorra)
* bug #22752 Improved how profiler errors are displayed on small screens (javiereguiluz)
* 3.3.0-RC1 (2017-05-17)
* bug #22715 [FrameworkBundle] remove Security deps from the require section (xabbuh)

View File

@ -24,20 +24,20 @@ Symfony is the result of the work of many people who made the code better
- Wouter De Jong (wouterj)
- Romain Neutron (romain)
- Grégoire Pineau (lyrixx)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
- Robin Chalas (chalas_r)
- Joseph Bielawski (stloyd)
- Maxime Steinhausser (ogizanagi)
- Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
- Martin Hasoň (hason)
- Maxime Steinhausser (ogizanagi)
- Jeremy Mikola (jmikola)
- Jean-François Simon (jfsimon)
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- Eriksen Costa (eriksencosta)
- Jules Pietri (heah)
- Sarah Khalil (saro0h)
- Roland Franssen (ro0)
- Sarah Khalil (saro0h)
- Jonathan Wage (jwage)
- Guilhem Niot (energetick)
- Diego Saint Esteben (dosten)
@ -49,10 +49,10 @@ Symfony is the result of the work of many people who made the code better
- Alexander Mols (asm89)
- Bulat Shakirzyanov (avalanche123)
- Peter Rehm (rpet)
- Iltar van der Berg (kjarli)
- Saša Stamenković (umpirsky)
- Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik
- Roland Franssen (ro0)
- Diego Saint Esteben (dii3g0)
- Konstantin Kudryashov (everzet)
- Bilal Amarni (bamarni)
@ -64,8 +64,8 @@ Symfony is the result of the work of many people who made the code better
- Michel Weimerskirch (mweimerskirch)
- Eric Clemmons (ericclemmons)
- Charles Sarrazin (csarrazi)
- Pierre du Plessis (pierredup)
- Christian Raue
- Pierre du Plessis (pierredup)
- Arnout Boks (aboks)
- Deni
- Henrik Westphal (snc)
@ -77,12 +77,12 @@ Symfony is the result of the work of many people who made the code better
- Lee McDermott
- Brandon Turner
- Luis Cordova (cordoval)
- Jérémy DERUSSÉ (jderusse)
- Graham Campbell (graham)
- Daniel Holmes (dholmes)
- Toni Uebernickel (havvg)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- Jérémy DERUSSÉ (jderusse)
- John Wards (johnwards)
- Dariusz Ruminski
- Fran Moreno (franmomu)
@ -92,8 +92,8 @@ Symfony is the result of the work of many people who made the code better
- Arnaud Le Blanc (arnaud-lb)
- Maxime STEINHAUSSER
- Michal Piotrowski (eventhorizon)
- Tim Nagel (merk)
- Issei Murasawa (issei_m)
- Tim Nagel (merk)
- Brice BERNARD (brikou)
- Alexander M. Turek (derrabus)
- Baptiste Clavié (talus)
@ -115,6 +115,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)
- Yonel Ceruto González (yonelceruto)
- Daniel Wehner (dawehner)
- Tugdual Saunier (tucksaun)
- Théo FIDRY (theofidry)
@ -122,7 +123,6 @@ Symfony is the result of the work of many people who made the code better
- Florian Lonqueu-Brochard (florianlb)
- Sebastiaan Stok (sstok)
- Stefano Sala (stefano.sala)
- Yonel Ceruto González (yonelceruto)
- Evgeniy (ewgraf)
- Juti Noppornpitak (shiroyuki)
- Tigran Azatyan (tigranazatyan)
@ -157,6 +157,7 @@ Symfony is the result of the work of many people who made the code better
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
- Artur Kotyrba
- David Maicher (dmaicher)
- jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent)
- James Halsall (jaitsu)
- Warnar Boekkooi (boekkooi)
@ -166,6 +167,7 @@ Symfony is the result of the work of many people who made the code better
- Possum
- Dorian Villet (gnutix)
- Richard Miller (mr_r_miller)
- Julien Falque (julienfalque)
- Mario A. Alvarez Garcia (nomack84)
- Dennis Benkert (denderello)
- Benjamin Dulau (dbenjamin)
@ -180,7 +182,6 @@ Symfony is the result of the work of many people who made the code better
- Daniel Espendiller
- sun (sun)
- Larry Garfield (crell)
- Julien Falque (julienfalque)
- Martin Schuhfuß (usefulthink)
- apetitpa
- Matthieu Bontemps (mbontemps)
@ -203,6 +204,7 @@ Symfony is the result of the work of many people who made the code better
- Tom Van Looy (tvlooy)
- Sven Paulus (subsven)
- Rui Marinho (ruimarinho)
- Marek Štípek (maryo)
- SpacePossum
- Eugene Wissner
- Julien Brochet (mewt)
@ -217,7 +219,6 @@ Symfony is the result of the work of many people who made the code better
- julien pauli (jpauli)
- Lorenz Schori
- Sébastien Lavoie (lavoiesl)
- David Maicher (dmaicher)
- Francois Zaninotto
- Alexander Kotynia (olden)
- Daniel Tschinder
@ -254,6 +255,7 @@ Symfony is the result of the work of many people who made the code better
- Albert Casademont (acasademont)
- Jhonny Lidfors (jhonne)
- Diego Agulló (aeoris)
- Andreas Schempp (aschempp)
- jdhoek
- Pavel Batanov (scaytrase)
- Nikita Konstantinov
@ -272,8 +274,8 @@ Symfony is the result of the work of many people who made the code better
- Michael Holm (hollo)
- Marc Weistroff (futurecat)
- Christian Schmidt
- Marek Štípek (maryo)
- Hidde Wieringa (hiddewie)
- Chad Sikorra (chadsikorra)
- Jordan Samouh (jordansamouh)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
@ -303,10 +305,10 @@ Symfony is the result of the work of many people who made the code better
- Francesc Rosàs (frosas)
- Massimiliano Arione (garak)
- Julien Galenski (ruian)
- Andreas Schempp (aschempp)
- Bongiraud Dominique
- janschoenherr
- Thomas Schulz (king2500)
- Dariusz Rumiński
- Berny Cantos (xphere81)
- Ricard Clau (ricardclau)
- Mark Challoner (markchalloner)
@ -385,7 +387,6 @@ Symfony is the result of the work of many people who made the code better
- Christophe L. (christophelau)
- Anthon Pang (robocoder)
- Emanuele Gaspari (inmarelibero)
- Dariusz Rumiński
- Sébastien Santoro (dereckson)
- Brian King
- Michel Salib (michelsalib)
@ -402,6 +403,7 @@ Symfony is the result of the work of many people who made the code better
- Jan Rosier (rosier)
- Thomas Royer (cydonia7)
- Josip Kruslin
- Asmir Mustafic (goetas)
- vagrant
- EdgarPE
- Florian Pfitzer (marmelatze)
@ -420,7 +422,6 @@ Symfony is the result of the work of many people who made the code better
- Marcin Sikoń (marphi)
- Dominik Zogg (dominik.zogg)
- Marek Pietrzak
- Chad Sikorra (chadsikorra)
- franek (franek)
- Christian Wahler
- Gintautas Miselis
@ -544,7 +545,6 @@ Symfony is the result of the work of many people who made the code better
- Andre Rømcke (andrerom)
- Nahuel Cuesta (ncuesta)
- Chris Boden (cboden)
- Asmir Mustafic (goetas)
- Stefan Gehrig (sgehrig)
- Hany el-Kerdany
- Wang Jingyu
@ -582,6 +582,7 @@ Symfony is the result of the work of many people who made the code better
- Sergey Kolodyazhnyy (skolodyazhnyy)
- umpirski
- Denis Brumann (dbrumann)
- Michael Babker (mbabker)
- Quentin de Longraye (quentinus95)
- Chris Heng (gigablah)
- Richard Bradley
@ -629,6 +630,7 @@ Symfony is the result of the work of many people who made the code better
- twifty
- Indra Gunawan (guind)
- Peter Ward
- insekticid
- Julien DIDIER (juliendidier)
- Dominik Ritter (dritter)
- Sebastian Grodzicki (sgrodzicki)
@ -745,6 +747,7 @@ Symfony is the result of the work of many people who made the code better
- Jan Kramer (jankramer)
- abdul malik ikhsan (samsonasik)
- Henry Snoek (snoek09)
- Jérémy M (th3mouk)
- Simone Di Maulo (toretto460)
- Christian Morgan
- Alexander Miehe (engerim)
@ -761,6 +764,7 @@ Symfony is the result of the work of many people who made the code better
- Douglas Reith (douglas_reith)
- Harry Walter (haswalt)
- Johnson Page (jwpage)
- Ruben Gonzalez (rubenruateltek)
- Michael Roterman (wtfzdotnet)
- Arno Geurts
- Adán Lobato (adanlobato)
@ -886,6 +890,7 @@ Symfony is the result of the work of many people who made the code better
- Eddie Jaoude
- Antanas Arvasevicius
- Haritz Iturbe (hizai)
- Baptiste Meyer (meyerbaptiste)
- Nerijus Arlauskas (nercury)
- SPolischook
- Diego Sapriza
@ -914,6 +919,7 @@ Symfony is the result of the work of many people who made the code better
- Jeremy Bush
- wizhippo
- Viacheslav Sychov
- Tyson Andre
- Carlos Ortega Huetos
- rpg600
- Péter Buri (burci)
@ -1014,6 +1020,7 @@ Symfony is the result of the work of many people who made the code better
- Conrad Kleinespel
- Sebastian Utz
- Adrien Gallou (agallou)
- Maks Rafalko (bornfree)
- Karol Sójko (karolsojko)
- Grzegorz Zdanowski (kiler129)
- sl_toto (sl_toto)
@ -1048,7 +1055,6 @@ Symfony is the result of the work of many people who made the code better
- Kim Laï Trinh
- Jason Desrosiers
- m.chwedziak
- insekticid
- Philip Frank
- Lance McNearney
- Giorgio Premi
@ -1058,6 +1064,7 @@ Symfony is the result of the work of many people who made the code better
- Alberto Pirovano (geezmo)
- Pete Mitchell (peterjmit)
- Tom Corrigan (tomcorrigan)
- adev
- Luis Galeas
- Martin Pärtel
- George Mponos (gmponos)
@ -1226,6 +1233,7 @@ Symfony is the result of the work of many people who made the code better
- Romain Dorgueil
- Grayson Koonce (breerly)
- Fabien LUCAS (flucas2)
- Indra Gunawan (indragunawan)
- Karim Cassam Chenaï (ka)
- Nicolas Bastien (nicolas_bastien)
- Denis (yethee)
@ -1273,6 +1281,7 @@ Symfony is the result of the work of many people who made the code better
- Daan van Renterghem
- Nicole Cordes
- Bram Van der Sype (brammm)
- Christopher Hertel (chertel)
- Guile (guile)
- Julien Moulin (lizjulien)
- Mauro Foti (skler)
@ -1291,6 +1300,7 @@ Symfony is the result of the work of many people who made the code better
- Johann Pardanaud
- Trevor Suarez
- gedrox
- Alan Bondarchuk
- dropfen
- Andrey Chernykh
- Edvinas Klovas
@ -1303,6 +1313,7 @@ Symfony is the result of the work of many people who made the code better
- bertillon
- Bertalan Attila
- Yannick Bensacq (cibou)
- Gawain Lynch (gawain)
- Luca Genuzio (genuzio)
- Hans Nilsson (hansnilsson)
- Andrew Marcinkevičius (ifdattic)
@ -1312,7 +1323,6 @@ Symfony is the result of the work of many people who made the code better
- Dan Patrick (mdpatrick)
- Rares Vlaseanu (raresvla)
- tante kinast (tante)
- Jérémy M (th3mouk)
- Vincent LEFORT (vlefort)
- Sadicov Vladimir (xtech)
- Kevin EMO (zarcox)
@ -1336,7 +1346,6 @@ Symfony is the result of the work of many people who made the code better
- Jonny Schmid (schmidjon)
- Götz Gottwald
- Veres Lajos
- Michael Babker
- grifx
- Robert Campbell
- Matt Lehner
@ -1415,9 +1424,11 @@ Symfony is the result of the work of many people who made the code better
- Yanick Witschi
- Ondrej Mirtes
- akimsko
- Ben Scott
- Youpie
- srsbiz
- Taylan Kasap
- Michael Orlitzky
- Nicolas A. Bérard-Nault
- Saem Ghani
- Stefan Oderbolz
@ -1430,6 +1441,7 @@ Symfony is the result of the work of many people who made the code better
- Ben
- Evgeniy Tetenchuk
- dasmfm
- Mathias Geat
- Arnaud Buathier (arnapou)
- chesteroni (chesteroni)
- Mauricio Lopez (diaspar)
@ -1516,6 +1528,7 @@ Symfony is the result of the work of many people who made the code better
- Abdulkadir N. A.
- Yevgen Kovalienia
- Lebnik
- Ondřej Führer
- Sema
- Elan Ruusamäe
- Thorsten Hallwas
@ -1568,6 +1581,7 @@ Symfony is the result of the work of many people who made the code better
- Bill Hance (billhance)
- Bernd Matzner (bmatzner)
- Bram Tweedegolf (bram_tweedegolf)
- Brandon Kelly (brandonkelly)
- Choong Wei Tjeng (choonge)
- Kousuke Ebihara (co3k)
- Loïc Vernet (coil)
@ -1675,6 +1689,7 @@ Symfony is the result of the work of many people who made the code better
- Andrew Carter (andrewcarteruk)
- Adam Elsodaney (archfizz)
- Daniel Kolvik (dkvk)
- Marc Lemay (flug)
- Jeroen De Dauw (jeroendedauw)
- Maxime COLIN (maximecolin)
- Muharrem Demirci (mdemirci)

View File

@ -7,7 +7,7 @@ if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) {
echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n";
exit(1);
}
if (PHP_VERSION_ID >= 70000 && !getenv('SYMFONY_PHPUNIT_VERSION')) {
if (\PHP_VERSION_ID >= 70000 && !getenv('SYMFONY_PHPUNIT_VERSION')) {
putenv('SYMFONY_PHPUNIT_VERSION=6.0');
}
putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit');

View File

@ -156,14 +156,20 @@ EOF
throw new \UnexpectedValueException('Unsupported callback type');
}
// filter out context/environment args
$args = array_filter($refl->getParameters(), function ($param) use ($entity) {
if ($entity->needsContext() && $param->getName() === 'context') {
return false;
}
$args = $refl->getParameters();
return !$param->getClass() || $param->getClass()->getName() !== 'Twig_Environment';
});
// filter out context/environment args
if ($entity->needsEnvironment()) {
array_shift($args);
}
if ($entity->needsContext()) {
array_shift($args);
}
if ($type === 'filters') {
// remove the value the filter is applied on
array_shift($args);
}
// format args
$args = array_map(function ($param) {
@ -174,11 +180,6 @@ EOF
return $param->getName();
}, $args);
if ($type === 'filters') {
// remove the value the filter is applied on
array_shift($args);
}
return $args;
}
}

View File

@ -113,7 +113,7 @@ if ($this->env->isDebug()) {
EOTXT;
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
$expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected);
} else {
$expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected);

View File

@ -67,7 +67,7 @@ class FormThemeTest extends TestCase
protected function getVariableGetter($name)
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
return sprintf('($context["%s"] ?? null)', $name, $name);
}

View File

@ -264,7 +264,7 @@ class SearchAndRenderBlockNodeTest extends TestCase
protected function getVariableGetter($name)
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
return sprintf('($context["%s"] ?? null)', $name, $name);
}

View File

@ -40,7 +40,7 @@ class TransNodeTest extends TestCase
protected function getVariableGetterWithoutStrictCheck($name)
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
return sprintf('($context["%s"] ?? null)', $name, $name);
}
@ -53,7 +53,7 @@ class TransNodeTest extends TestCase
return sprintf('(isset($context["%s"]) || array_key_exists("%s", $context) ? $context["%s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%s" does not exist.\', 0, $this->getSourceContext()); })())', $name, $name, $name, $name);
}
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
return sprintf('($context["%s"] ?? $this->getContext($context, "%s"))', $name, $name, $name);
}

View File

@ -11,9 +11,12 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use Symfony\Component\Cache\Adapter\TraceableAdapter;
use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/**
@ -34,17 +37,30 @@ class CacheCollectorPass implements CompilerPassInterface
$collectorDefinition = $container->getDefinition('data_collector.cache');
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
if ($container->getDefinition($id)->isAbstract()) {
$definition = $container->getDefinition($id);
if ($definition->isAbstract()) {
continue;
}
$container->register($id.'.recorder', TraceableAdapter::class)
->setDecoratedService($id)
->addArgument(new Reference($id.'.recorder.inner'))
->setPublic(false);
$recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class);
$recorder->setTags($definition->getTags());
$recorder->setPublic($definition->isPublic());
$recorder->setArguments(array(new Reference($innerId = $id.'.recorder_inner')));
$definition->setTags(array());
$definition->setPublic(false);
if ($types = $definition->getAutowiringTypes(false)) {
$recorder->setAutowiringTypes($types);
$definition->setAutowiringTypes(array());
}
$container->setDefinition($innerId, $definition);
$container->setDefinition($id, $recorder);
// Tell the collector to add the new instance
$collectorDefinition->addMethodCall('addInstance', array($id, new Reference($id)));
$collectorDefinition->setPublic(false);
}
}
}

View File

@ -115,7 +115,7 @@ class FrameworkBundle extends Bundle
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255);
$this->addCompilerPassIfExists($container, ConfigCachePass::class);
$container->addCompilerPass(new CacheCollectorPass());
$container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING);
}
}

View File

@ -7,8 +7,8 @@
<services>
<defaults public="false" />
<!-- DataCollector -->
<service id="data_collector.cache" class="Symfony\Component\Cache\DataCollector\CacheDataCollector">
<!-- DataCollector (public to prevent inlining, made private in CacheCollectorPass) -->
<service id="data_collector.cache" class="Symfony\Component\Cache\DataCollector\CacheDataCollector" public="true">
<tag name="data_collector" template="@WebProfiler/Collector/cache.html.twig" id="cache" priority="275" />
</service>
</services>

View File

@ -0,0 +1,49 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
use Symfony\Component\Cache\Adapter\TraceableAdapter;
use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter;
use Symfony\Component\Cache\DataCollector\CacheDataCollector;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class CacheCollectorPassTest extends TestCase
{
public function testProcess()
{
$container = new ContainerBuilder();
$container
->register('fs', FilesystemAdapter::class)
->addTag('cache.pool');
$container
->register('tagged_fs', TagAwareAdapter::class)
->addArgument(new Reference('fs'))
->addTag('cache.pool');
$collector = $container->register('data_collector.cache', CacheDataCollector::class);
(new CacheCollectorPass())->process($container);
$this->assertEquals(array(
array('addInstance', array('fs', new Reference('fs'))),
array('addInstance', array('tagged_fs', new Reference('tagged_fs'))),
), $collector->getMethodCalls());
$this->assertSame(TraceableAdapter::class, $container->findDefinition('fs')->getClass());
$this->assertSame(TraceableTagAwareAdapter::class, $container->getDefinition('tagged_fs')->getClass());
$this->assertFalse($collector->isPublic(), 'The "data_collector.cache" should be private after processing');
}
}

View File

@ -85,7 +85,7 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
foreach ($files as $file) {
$this->parseTokens(token_get_all(file_get_contents($file)), $catalog);
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
gc_mem_caches();
}

View File

@ -478,6 +478,11 @@
addEventListener(toggles[i], 'click', function(e) {
e.preventDefault();
if ('' !== window.getSelection().toString()) {
/* Don't do anything on text selection */
return;
}
var toggle = e.target || e.srcElement;
/* needed because when the toggle contains HTML contents, user can click */
@ -507,6 +512,14 @@
var altContent = toggle.getAttribute('data-toggle-alt-content');
toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
});
/* Prevents from disallowing clicks on links inside toggles */
var toggleLinks = document.querySelectorAll('.sf-toggle a');
for (var i = 0; i < toggleLinks.length; i++) {
addEventListener(toggleLinks[i], 'click', function(e) {
e.stopPropagation();
});
}
}
}
};

View File

@ -89,7 +89,6 @@ header .container { display: flex; justify-content: space-between; }
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
.trace + .trace { margin-top: 30px; }
.trace-head { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
.trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; }
.trace-head .icon { position: absolute; right: 0; top: 0; }

View File

@ -478,6 +478,11 @@
addEventListener(toggles[i], 'click', function(e) {
e.preventDefault();
if ('' !== window.getSelection().toString()) {
/* Don't do anything on text selection */
return;
}
var toggle = e.target || e.srcElement;
/* needed because when the toggle contains HTML contents, user can click */
@ -508,6 +513,14 @@
toggle.innerHTML = currentContent !== altContent ? altContent : originalContent;
});
}
/* Prevents from disallowing clicks on links inside toggles */
var toggleLinks = document.querySelectorAll('.sf-toggle a');
for (var i = 0; i < toggleLinks.length; i++) {
addEventListener(toggleLinks[i], 'click', function(e) {
e.stopPropagation();
});
}
}
};
})();

View File

@ -22,7 +22,7 @@ use Psr\Cache\CacheItemInterface;
*/
class TraceableAdapter implements AdapterInterface
{
private $pool;
protected $pool;
private $calls = array();
public function __construct(AdapterInterface $pool)
@ -107,7 +107,7 @@ class TraceableAdapter implements AdapterInterface
*/
public function getItems(array $keys = array())
{
$event = $this->start(__FUNCTION__, $keys);
$event = $this->start(__FUNCTION__);
try {
$result = $this->pool->getItems($keys);
} finally {
@ -177,7 +177,7 @@ class TraceableAdapter implements AdapterInterface
}
}
private function start($name)
protected function start($name)
{
$this->calls[] = $event = new TraceableAdapterEvent();
$event->name = $name;

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Cache\Adapter;
/**
* @author Robin Chalas <robin.chalas@gmail.com>
*/
class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface
{
public function __construct(TagAwareAdapterInterface $pool)
{
parent::__construct($pool);
}
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags)
{
$event = $this->start(__FUNCTION__);
try {
return $event->result = $this->pool->invalidateTags($tags);
} finally {
$event->end = microtime(true);
}
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter;
class TraceableTagAwareAdapterTest extends TraceableAdapterTest
{
public function testInvalidateTags()
{
$pool = new TraceableTagAwareAdapter(new TagAwareAdapter(new FilesystemAdapter()));
$pool->invalidateTags(array('foo'));
$calls = $pool->getCalls();
$this->assertCount(1, $calls);
$call = $calls[0];
$this->assertSame('invalidateTags', $call->name);
$this->assertSame(0, $call->hits);
$this->assertSame(0, $call->misses);
$this->assertNotEmpty($call->start);
$this->assertNotEmpty($call->end);
}
}

View File

@ -126,6 +126,6 @@ EOF;
*/
private function initialize()
{
$this->values = @(include $this->file) ?: array();
$this->values = file_exists($this->file) ? (include $this->file ?: array()) : array();
}
}

View File

@ -262,7 +262,7 @@ REGEX;
$output .= self::compressCode($rawChunk);
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
unset($tokens, $rawChunk);
gc_mem_caches();

View File

@ -68,7 +68,7 @@ class ClassMapGenerator
$classes = self::findClasses($path);
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
gc_mem_caches();
}

View File

@ -83,13 +83,18 @@ abstract class FileLoader extends Loader
*/
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
{
if (is_string($resource) && false !== strpbrk($resource, '*?{[')) {
if (is_string($resource) && strlen($resource) !== $i = strcspn($resource, '*?{[')) {
$ret = array();
foreach ($this->glob($resource, false, $_, true) as $path => $info) {
$ret[] = $this->doImport($path, $type, $ignoreErrors, $sourceResource);
$isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/');
foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath) as $path => $info) {
if (null !== $res = $this->doImport($path, $type, $ignoreErrors, $sourceResource)) {
$ret[] = $res;
}
$isSubpath = true;
}
if ($ret) {
return count($ret) > 1 ? $ret : $ret[0];
if ($isSubpath) {
return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null);
}
}
@ -104,7 +109,7 @@ abstract class FileLoader extends Loader
if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
$prefix = $pattern;
$pattern = '';
} elseif (0 === $i) {
} elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) {
$prefix = '.';
$pattern = '/'.$pattern;
} else {

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Config\Tests\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
@ -74,6 +75,21 @@ class FileLoaderTest extends TestCase
$this->assertSame('[foo]', $loader->import('[foo]'));
}
public function testImportWithNoGlobMatch()
{
$locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
$loader = new TestFileLoader($locatorMock);
$this->assertNull($loader->import('./*.abc'));
}
public function testImportWithSimpleGlob()
{
$loader = new TestFileLoader(new FileLocator(__DIR__));
$this->assertSame(__FILE__, strtr($loader->import('FileLoaderTest.*'), '/', DIRECTORY_SEPARATOR));
}
}
class TestFileLoader extends FileLoader

View File

@ -316,7 +316,6 @@ EOF;
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
.trace + .trace { margin-top: 30px; }
.trace-head { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
.trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }

View File

@ -61,7 +61,7 @@ class DebugClassLoaderTest extends TestCase
public function testUnsilencing()
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
}
if (defined('HHVM_VERSION')) {
@ -109,7 +109,7 @@ class DebugClassLoaderTest extends TestCase
} catch (\ErrorException $exception) {
// if an exception is thrown, the test passed
$this->assertStringStartsWith(__FILE__, $exception->getFile());
if (PHP_VERSION_ID < 70000) {
if (\PHP_VERSION_ID < 70000) {
$this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
$this->assertEquals(E_STRICT, $exception->getSeverity());
} else {
@ -245,7 +245,7 @@ class DebugClassLoaderTest extends TestCase
public function testReservedForPhp7()
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 already prevents using reserved names.');
}

View File

@ -44,9 +44,27 @@ class AutowireExceptionPass implements CompilerPassInterface
$this->inlineServicePass = null;
foreach ($exceptions as $exception) {
if ($container->hasDefinition($exception->getServiceId()) || in_array($exception->getServiceId(), $inlinedIds)) {
if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) {
throw $exception;
}
}
}
private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds)
{
if ($container->hasDefinition($serviceId)) {
return true;
}
// was the service inlined? Of so, does its parent service exist?
if (isset($inlinedIds[$serviceId])) {
foreach ($inlinedIds[$serviceId] as $parentId) {
if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) {
return true;
}
}
}
return false;
}
}

View File

@ -114,7 +114,7 @@ class AutowirePass extends AbstractRecursivePass
private function doProcessValue($value, $isRoot = false)
{
if ($value instanceof TypedReference) {
if ($ref = $this->getAutowiredReference($value)) {
if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) {
return $ref;
}
$this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
@ -133,7 +133,13 @@ class AutowirePass extends AbstractRecursivePass
$autowiredMethods = $this->getMethodsToAutowire($reflectionClass);
$methodCalls = $value->getMethodCalls();
if ($constructor = $this->getConstructor($value, false)) {
try {
$constructor = $this->getConstructor($value, false);
} catch (RuntimeException $e) {
throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
}
if ($constructor) {
array_unshift($methodCalls, array($constructor, $value->getArguments()));
}
@ -242,7 +248,7 @@ class AutowirePass extends AbstractRecursivePass
*
* @return array The autowired arguments
*
* @throws RuntimeException
* @throws AutowiringFailedException
*/
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments)
{
@ -276,7 +282,7 @@ class AutowirePass extends AbstractRecursivePass
continue;
}
if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''))) {
if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''), 'for '.sprintf('argument "$%s" of method "%s()"', $parameter->name, $class.'::'.$method))) {
$failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
if ($parameter->isDefaultValueAvailable()) {
@ -310,7 +316,7 @@ class AutowirePass extends AbstractRecursivePass
/**
* @return TypedReference|null A reference to the service matching the given type, if any
*/
private function getAutowiredReference(TypedReference $reference)
private function getAutowiredReference(TypedReference $reference, $deprecationMessage)
{
$this->lastFailure = null;
$type = $reference->getType();
@ -328,7 +334,14 @@ class AutowirePass extends AbstractRecursivePass
}
if (isset($this->types[$type])) {
@trigger_error(sprintf('Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0. You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type), E_USER_DEPRECATED);
$message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.';
if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) {
$message .= ' '.$aliasSuggestion;
} else {
$message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type);
}
@trigger_error($message, E_USER_DEPRECATED);
return new TypedReference($this->types[$type], $type);
}
@ -484,25 +497,9 @@ class AutowirePass extends AbstractRecursivePass
private function createTypeAlternatives(TypedReference $reference)
{
$type = $reference->getType();
$aliases = array();
foreach (class_parents($type) + class_implements($type) as $parent) {
if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
$aliases[] = $parent;
}
}
if (1 < $len = count($aliases)) {
$message = ' Try changing the type-hint to one of its parents: ';
for ($i = 0, --$len; $i < $len; ++$i) {
$message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
}
$message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
return $message;
}
if ($aliases) {
return sprintf(' Try changing the type-hint to "%s" instead.', $aliases[0]);
// try suggesting available aliases first
if ($message = $this->getAliasesSuggestionForType($type = $reference->getType())) {
return ' '.$message;
}
if (isset($this->ambiguousServiceTypes[$type])) {
@ -542,4 +539,29 @@ class AutowirePass extends AbstractRecursivePass
return $methodArgumentsMetadata;
}
private function getAliasesSuggestionForType($type, $extraContext = null)
{
$aliases = array();
foreach (class_parents($type) + class_implements($type) as $parent) {
if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
$aliases[] = $parent;
}
}
$extraContext = $extraContext ? ' '.$extraContext : '';
if (1 < $len = count($aliases)) {
$message = sprintf('Try changing the type-hint%s to one of its parents: ', $extraContext);
for ($i = 0, --$len; $i < $len; ++$i) {
$message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
}
$message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
return $message;
}
if ($aliases) {
return sprintf('Try changing the type-hint%s to "%s" instead.', $extraContext, $aliases[0]);
}
}
}

View File

@ -36,7 +36,9 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
/**
* Returns an array of all services inlined by this pass.
*
* @return array Service id strings
* The key is the inlined service id and its value is the list of services it was inlined into.
*
* @return array
*/
public function getInlinedServiceIds()
{
@ -57,7 +59,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
$this->inlinedServiceIds[] = $id;
$this->inlinedServiceIds[$id][] = $this->currentId;
if ($definition->isShared()) {
return $definition;

View File

@ -18,7 +18,7 @@ class AutowiringFailedException extends RuntimeException
{
private $serviceId;
public function __construct($serviceId, $message = '', $code = 0, Exception $previous = null)
public function __construct($serviceId, $message = '', $code = 0, \Exception $previous = null)
{
$this->serviceId = $serviceId;

View File

@ -54,7 +54,7 @@ class AutowireExceptionPassTest extends TestCase
$autowirePass = $this->getMockBuilder(AutowirePass::class)
->getMock();
$autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message');
$autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message');
$autowirePass->expects($this->any())
->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException)));
@ -63,10 +63,16 @@ class AutowireExceptionPassTest extends TestCase
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array('foo_service_id')));
->will($this->returnValue(array(
// a_service inlined into b_service
'a_service' => array('b_service'),
// b_service inlined into c_service
'b_service' => array('c_service'),
)));
// don't register the foo_service_id service
$container = new ContainerBuilder();
// ONLY register c_service in the final container
$container->register('c_service', 'stdClass');
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
@ -78,6 +84,37 @@ class AutowireExceptionPassTest extends TestCase
}
}
public function testDoNotThrowExceptionIfServiceInlinedButRemoved()
{
$autowirePass = $this->getMockBuilder(AutowirePass::class)
->getMock();
$autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message');
$autowirePass->expects($this->any())
->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException)));
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array(
// a_service inlined into b_service
'a_service' => array('b_service'),
// b_service inlined into c_service
'b_service' => array('c_service'),
)));
// do NOT register c_service in the container
$container = new ContainerBuilder();
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
$pass->process($container);
// mark the test as passed
$this->assertTrue(true);
}
public function testNoExceptionIfServiceRemoved()
{
$autowirePass = $this->getMockBuilder(AutowirePass::class)

View File

@ -78,6 +78,28 @@ class AutowirePassTest extends TestCase
$this->assertEquals(B::class, (string) $container->getDefinition('c')->getArgument(0));
}
/**
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead.
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessageInSymfony4 Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service.
*/
public function testProcessLegacyAutowireWithAvailableInterface()
{
$container = new ContainerBuilder();
$container->setAlias(AInterface::class, B::class);
$container->register(B::class);
$cDefinition = $container->register('c', __NAMESPACE__.'\C');
$cDefinition->setAutowired(true);
(new ResolveClassPass())->process($container);
(new AutowirePass())->process($container);
$this->assertCount(1, $container->getDefinition('c')->getArguments());
$this->assertEquals(B::class, (string) $container->getDefinition('c')->getArgument(0));
}
/**
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\F" service to "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" instead.
@ -151,7 +173,21 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Unable to resolve service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public.
*/
public function testPrivateConstructorThrowsAutowireException()
{
$container = new ContainerBuilder();
$container->autowire('private_service', __NAMESPACE__.'\PrivateConstructor');
$pass = new AutowirePass(true);
$pass->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2", "c3".
*/
public function testTypeCollision()
@ -169,7 +205,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
*/
public function testTypeNotGuessable()
@ -186,7 +222,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
*/
public function testTypeNotGuessableWithSubclass()
@ -203,7 +239,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists.
*/
public function testTypeNotGuessableNoServicesFound()
@ -322,7 +358,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.
*/
public function testClassNotFoundThrowsException()
@ -337,7 +373,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class does not exist.
*/
public function testParentClassNotFoundThrowsException()
@ -354,7 +390,7 @@ class AutowirePassTest extends TestCase
/**
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead.
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service.
*/
public function testDontUseAbstractServices()
@ -399,7 +435,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" must have a type-hint or be given a value explicitly.
*/
public function testScalarArgsCannotBeAutowired()
@ -607,7 +643,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2".
*/
public function testSetterInjectionCollisionThrowsException()
@ -626,7 +662,7 @@ class AutowirePassTest extends TestCase
/**
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead.
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service.
*/
public function testProcessDoesNotTriggerDeprecations()
@ -677,7 +713,7 @@ class AutowirePassTest extends TestCase
/**
* @dataProvider provideNotWireableCalls
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
*/
public function testNotWireableCalls($method, $expectedMsg)
{
@ -716,8 +752,8 @@ class AutowirePassTest extends TestCase
/**
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "i" service to "Symfony\Component\DependencyInjection\Tests\Compiler\I" instead.
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessageInSymfony4 Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
*/
public function testByIdAlternative()
@ -734,7 +770,26 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @group legacy
* @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for "Symfony\Component\DependencyInjection\Tests\Compiler\A" in "Symfony\Component\DependencyInjection\Tests\Compiler\Bar" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead.
*/
public function testTypedReferenceDeprecationNotice()
{
$container = new ContainerBuilder();
$container->register('aClass', A::class);
$container->setAlias(AInterface::class, 'aClass');
$container
->register('bar', Bar::class)
->setProperty('a', array(new TypedReference(A::class, A::class, Bar::class)))
;
$pass = new AutowirePass();
$pass->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
*/
public function testExceptionWhenAliasExists()
@ -754,7 +809,7 @@ class AutowirePassTest extends TestCase
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
* @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to one of these existing services: "i", "i2".
*/
public function testExceptionWhenAliasDoesNotExist()
@ -784,7 +839,11 @@ class Bar
}
}
class A
interface AInterface
{
}
class A implements AInterface
{
public static function create(Foo $foo)
{
@ -1091,3 +1150,10 @@ class NotWireable
{
}
}
class PrivateConstructor
{
private function __construct()
{
}
}

View File

@ -252,7 +252,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$this->assertSame('inline', (string) $values[0]);
}
public function testGetInlinedServiceIds()
public function testGetInlinedServiceIdData()
{
$container = new ContainerBuilder();
$container
@ -265,7 +265,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
;
$container
->register('service')
->register('other_service')
->setArguments(array(new Reference('inlinable.service')))
;
@ -273,7 +273,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass));
$repeatedPass->process($container);
$this->assertEquals(array('inlinable.service'), $inlinePass->getInlinedServiceIds());
$this->assertEquals(array('inlinable.service' => array('other_service')), $inlinePass->getInlinedServiceIds());
}
protected function process(ContainerBuilder $container)

View File

@ -116,7 +116,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher
public function hasListeners($eventName = null)
{
if (null === $eventName) {
return (bool) count($this->listenerIds) || (bool) count($this->listeners);
return count($this->listenerIds) || count($this->listeners) || parent::hasListeners();
}
if (isset($this->listenerIds[$eventName])) {

View File

@ -11,10 +11,11 @@
namespace Symfony\Component\EventDispatcher\DependencyInjection;
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -78,7 +79,7 @@ class RegisterListenersPass implements CompilerPassInterface
$event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
}
$definition->addMethodCall('addListener', array($event['event'], new ClosureProxyArgument($id, $event['method']), $priority));
$definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority));
}
}
@ -103,7 +104,7 @@ class RegisterListenersPass implements CompilerPassInterface
ExtractingEventDispatcher::$subscriber = $class;
$extractingDispatcher->addSubscriber($extractingDispatcher);
foreach ($extractingDispatcher->listeners as $args) {
$args[1] = new ClosureProxyArgument($id, $args[1]);
$args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]);
$definition->addMethodCall('addListener', $args);
}
$extractingDispatcher->listeners = array();

View File

@ -24,6 +24,7 @@ namespace Symfony\Component\EventDispatcher;
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Jordan Alliot <jordan.alliot@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
class EventDispatcher implements EventDispatcherInterface
{
@ -52,7 +53,7 @@ class EventDispatcher implements EventDispatcherInterface
public function getListeners($eventName = null)
{
if (null !== $eventName) {
if (!isset($this->listeners[$eventName])) {
if (empty($this->listeners[$eventName])) {
return array();
}
@ -77,13 +78,23 @@ class EventDispatcher implements EventDispatcherInterface
*/
public function getListenerPriority($eventName, $listener)
{
if (!isset($this->listeners[$eventName])) {
if (empty($this->listeners[$eventName])) {
return;
}
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
if (false !== in_array($listener, $listeners, true)) {
return $priority;
foreach ($listeners as $k => $v) {
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
$v[0] = $v[0]();
$this->listeners[$eventName][$priority][$k] = $v;
}
if ($v === $listener) {
return $priority;
}
}
}
}
@ -93,7 +104,17 @@ class EventDispatcher implements EventDispatcherInterface
*/
public function hasListeners($eventName = null)
{
return (bool) $this->getListeners($eventName);
if (null !== $eventName) {
return !empty($this->listeners[$eventName]);
}
foreach ($this->listeners as $eventListeners) {
if ($eventListeners) {
return true;
}
}
return false;
}
/**
@ -110,13 +131,30 @@ class EventDispatcher implements EventDispatcherInterface
*/
public function removeListener($eventName, $listener)
{
if (!isset($this->listeners[$eventName])) {
if (empty($this->listeners[$eventName])) {
return;
}
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
if (false !== ($key = array_search($listener, $listeners, true))) {
unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
foreach ($listeners as $k => $v) {
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
$v[0] = $v[0]();
}
if ($v === $listener) {
unset($listeners[$k], $this->sorted[$eventName]);
} else {
$listeners[$k] = $v;
}
}
if ($listeners) {
$this->listeners[$eventName][$priority] = $listeners;
} else {
unset($this->listeners[$eventName][$priority]);
}
}
}
@ -183,6 +221,16 @@ class EventDispatcher implements EventDispatcherInterface
private function sortListeners($eventName)
{
krsort($this->listeners[$eventName]);
$this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
$this->sorted[$eventName] = array();
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $k => $listener) {
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
$this->listeners[$eventName][$priority][$k] = $listener;
}
$this->sorted[$eventName][] = $listener;
}
}
}
}

View File

@ -302,6 +302,73 @@ abstract class AbstractEventDispatcherTest extends TestCase
$this->assertFalse($this->dispatcher->hasListeners('foo'));
$this->assertFalse($this->dispatcher->hasListeners());
}
public function testHasListenersIsLazy()
{
$called = 0;
$listener = array(function () use (&$called) { ++$called; }, 'onFoo');
$this->dispatcher->addListener('foo', $listener);
$this->assertTrue($this->dispatcher->hasListeners());
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->assertSame(0, $called);
}
public function testDispatchLazyListener()
{
$called = 0;
$factory = function () use (&$called) {
++$called;
return new TestWithDispatcher();
};
$this->dispatcher->addListener('foo', array($factory, 'foo'));
$this->assertSame(0, $called);
$this->dispatcher->dispatch('foo', new Event());
$this->dispatcher->dispatch('foo', new Event());
$this->assertSame(1, $called);
}
public function testRemoveFindsLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', array($factory, 'foo'));
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->dispatcher->removeListener('foo', array($test, 'foo'));
$this->assertFalse($this->dispatcher->hasListeners('foo'));
$this->dispatcher->addListener('foo', array($test, 'foo'));
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->dispatcher->removeListener('foo', array($factory, 'foo'));
$this->assertFalse($this->dispatcher->hasListeners('foo'));
}
public function testPriorityFindsLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', array($factory, 'foo'), 3);
$this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo')));
$this->dispatcher->removeListener('foo', array($factory, 'foo'));
$this->dispatcher->addListener('foo', array($test, 'foo'), 5);
$this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo')));
}
public function testGetLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', array($factory, 'foo'), 3);
$this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo'));
$this->dispatcher->removeListener('foo', array($test, 'foo'));
$this->dispatcher->addListener('bar', array($factory, 'foo'), 3);
$this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners());
}
}
class CallableClass

View File

@ -12,8 +12,9 @@
namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
class RegisterListenersPassTest extends TestCase
@ -127,17 +128,17 @@ class RegisterListenersPassTest extends TestCase
$registerListenersPass->process($container);
$definition = $container->getDefinition('event_dispatcher');
$expected_calls = array(
$expectedCalls = array(
array(
'addListener',
array(
'event',
new ClosureProxyArgument('foo', 'onEvent'),
array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'),
0,
),
),
);
$this->assertEquals($expected_calls, $definition->getMethodCalls());
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
}
/**

View File

@ -31,7 +31,7 @@ abstract class FilterIterator extends \FilterIterator
*/
public function rewind()
{
if (PHP_VERSION_ID > 50607 || (PHP_VERSION_ID > 50523 && PHP_VERSION_ID < 50600)) {
if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
parent::rewind();
return;

View File

@ -119,7 +119,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
}
// @see https://bugs.php.net/68557
if (PHP_VERSION_ID < 50523 || PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 50607) {
if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
parent::next();
}

View File

@ -162,6 +162,10 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
$dateFormat = $this->dateFormat;
$timeFormat = $this->timeFormat;
$timezone = $ignoreTimezone ? 'UTC' : $this->outputTimezone;
if (class_exists('IntlTimeZone', false)) {
// see https://bugs.php.net/bug.php?id=66323
$timezone = \IntlTimeZone::createTimeZone($timezone);
}
$calendar = $this->calendar;
$pattern = $this->pattern;

View File

@ -82,7 +82,8 @@ class DateType extends AbstractType
\Locale::getDefault(),
$dateFormat,
$timeFormat,
null,
// see https://bugs.php.net/bug.php?id=66323
class_exists('IntlTimeZone', false) ? \IntlTimeZone::createDefault() : null,
$calendar,
$pattern
);

View File

@ -18,19 +18,14 @@ namespace Symfony\Component\Form\Guess;
*/
class ValueGuess extends Guess
{
/**
* The guessed value.
*
* @var array
*/
private $value;
/**
* Constructor.
*
* @param string $value The guessed value
* @param int $confidence The confidence that the guessed class name
* is correct
* @param string|int|bool|null $value The guessed value
* @param int $confidence The confidence that the guessed class name
* is correct
*/
public function __construct($value, $confidence)
{
@ -42,7 +37,7 @@ class ValueGuess extends Guess
/**
* Returns the guessed value.
*
* @return mixed
* @return string|int|bool|null
*/
public function getValue()
{

View File

@ -1577,7 +1577,7 @@ class Request
public function getContent($asResource = false)
{
$currentContentIsResource = is_resource($this->content);
if (PHP_VERSION_ID < 50600 && false === $this->content) {
if (\PHP_VERSION_ID < 50600 && false === $this->content) {
throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.');
}

View File

@ -1057,7 +1057,7 @@ class RequestTest extends TestCase
*/
public function testGetContentCantBeCalledTwiceWithResources($first, $second)
{
if (PHP_VERSION_ID >= 50600) {
if (\PHP_VERSION_ID >= 50600) {
$this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.');
}

View File

@ -138,6 +138,9 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
$logs = array();
foreach (file($file, FILE_IGNORE_NEW_LINES) as $log) {
$log = explode(': ', $log, 2);
if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) {
$log = array('Unknown Compiler Pass', implode(': ', $log));
}
$logs[$log[0]][] = array('message' => $log[1]);
}

View File

@ -822,7 +822,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
$output .= $rawChunk;
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
unset($tokens, $rawChunk);
gc_mem_caches();

View File

@ -0,0 +1,4 @@
Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Psr\Container\ContainerInterface"; reason: private alias.
Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.
Some custom logging message
With ending :

View File

@ -17,6 +17,27 @@ use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
class LoggerDataCollectorTest extends TestCase
{
public function testCollectWithUnexpectedFormat()
{
$logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock();
$logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo'));
$logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array()));
$c = new LoggerDataCollector($logger, __DIR__.'/');
$c->lateCollect();
$compilerLogs = $c->getCompilerLogs()->getValue('message');
$this->assertSame(array(
array('message' => 'Removed service "Psr\Container\ContainerInterface"; reason: private alias.'),
array('message' => 'Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.'),
), $compilerLogs['Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass']);
$this->assertSame(array(
array('message' => 'Some custom logging message'),
array('message' => 'With ending :'),
), $compilerLogs['Unknown Compiler Pass']);
}
/**
* @dataProvider getCollectTestData
*/

View File

@ -435,7 +435,7 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
public function testFormatWithDateTimeZoneGmtOffset()
{
if (defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) {
if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID <= 50509) {
$this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.');
}

View File

@ -195,7 +195,7 @@ class PropertyAccessor implements PropertyAccessorInterface
$overwrite = true;
try {
if (PHP_VERSION_ID < 70000 && false === self::$previousErrorHandler) {
if (\PHP_VERSION_ID < 70000 && false === self::$previousErrorHandler) {
self::$previousErrorHandler = set_error_handler(self::$errorHandler);
}

View File

@ -64,7 +64,7 @@ class AnnotationFileLoader extends FileLoader
$collection->addResource(new FileResource($path));
$collection->addCollection($this->loader->load($class, $type));
}
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
gc_mem_caches();
}

View File

@ -238,7 +238,7 @@ EOF;
$hostMatches = false;
$methods = $route->getMethods();
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods));
$regex = $compiledRoute->getRegex();
if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#'.(substr($regex, -1) === 'u' ? 'u' : ''), $regex, $m)) {

View File

@ -0,0 +1,204 @@
<?php
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;
/**
* ProjectUrlMatcher.
*
* This class has been auto-generated
* by the Symfony Routing Component.
*/
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
{
/**
* Constructor.
*/
public function __construct(RequestContext $context)
{
$this->context = $context;
}
public function match($pathinfo)
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
if (0 === strpos($pathinfo, '/trailing/simple')) {
// simple_trailing_slash_no_methods
if ('/trailing/simple/no-methods/' === $pathinfo) {
return array('_route' => 'simple_trailing_slash_no_methods');
}
// simple_trailing_slash_GET_method
if ('/trailing/simple/get-method/' === $pathinfo) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_simple_trailing_slash_GET_method;
}
return array('_route' => 'simple_trailing_slash_GET_method');
}
not_simple_trailing_slash_GET_method:
// simple_trailing_slash_HEAD_method
if ('/trailing/simple/head-method/' === $pathinfo) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_simple_trailing_slash_HEAD_method;
}
return array('_route' => 'simple_trailing_slash_HEAD_method');
}
not_simple_trailing_slash_HEAD_method:
// simple_trailing_slash_POST_method
if ('/trailing/simple/post-method/' === $pathinfo) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_simple_trailing_slash_POST_method;
}
return array('_route' => 'simple_trailing_slash_POST_method');
}
not_simple_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/trailing/regex')) {
// regex_trailing_slash_no_methods
if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) {
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ());
}
// regex_trailing_slash_GET_method
if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_regex_trailing_slash_GET_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ());
}
not_regex_trailing_slash_GET_method:
// regex_trailing_slash_HEAD_method
if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_regex_trailing_slash_HEAD_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ());
}
not_regex_trailing_slash_HEAD_method:
// regex_trailing_slash_POST_method
if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_regex_trailing_slash_POST_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ());
}
not_regex_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/not-trailing/simple')) {
// simple_not_trailing_slash_no_methods
if ('/not-trailing/simple/no-methods' === $pathinfo) {
return array('_route' => 'simple_not_trailing_slash_no_methods');
}
// simple_not_trailing_slash_GET_method
if ('/not-trailing/simple/get-method' === $pathinfo) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_simple_not_trailing_slash_GET_method;
}
return array('_route' => 'simple_not_trailing_slash_GET_method');
}
not_simple_not_trailing_slash_GET_method:
// simple_not_trailing_slash_HEAD_method
if ('/not-trailing/simple/head-method' === $pathinfo) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_simple_not_trailing_slash_HEAD_method;
}
return array('_route' => 'simple_not_trailing_slash_HEAD_method');
}
not_simple_not_trailing_slash_HEAD_method:
// simple_not_trailing_slash_POST_method
if ('/not-trailing/simple/post-method' === $pathinfo) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_simple_not_trailing_slash_POST_method;
}
return array('_route' => 'simple_not_trailing_slash_POST_method');
}
not_simple_not_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/not-trailing/regex')) {
// regex_not_trailing_slash_no_methods
if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ());
}
// regex_not_trailing_slash_GET_method
if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_regex_not_trailing_slash_GET_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ());
}
not_regex_not_trailing_slash_GET_method:
// regex_not_trailing_slash_HEAD_method
if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_regex_not_trailing_slash_HEAD_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ());
}
not_regex_not_trailing_slash_HEAD_method:
// regex_not_trailing_slash_POST_method
if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_regex_not_trailing_slash_POST_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ());
}
not_regex_not_trailing_slash_POST_method:
}
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
}
}

View File

@ -0,0 +1,228 @@
<?php
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\RequestContext;
/**
* ProjectUrlMatcher.
*
* This class has been auto-generated
* by the Symfony Routing Component.
*/
class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher
{
/**
* Constructor.
*/
public function __construct(RequestContext $context)
{
$this->context = $context;
}
public function match($pathinfo)
{
$allow = array();
$pathinfo = rawurldecode($pathinfo);
$trimmedPathinfo = rtrim($pathinfo, '/');
$context = $this->context;
$request = $this->request;
$requestMethod = $canonicalMethod = $context->getMethod();
$scheme = $context->getScheme();
if ('HEAD' === $requestMethod) {
$canonicalMethod = 'GET';
}
if (0 === strpos($pathinfo, '/trailing/simple')) {
// simple_trailing_slash_no_methods
if ('/trailing/simple/no-methods' === $trimmedPathinfo) {
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'simple_trailing_slash_no_methods');
}
return array('_route' => 'simple_trailing_slash_no_methods');
}
// simple_trailing_slash_GET_method
if ('/trailing/simple/get-method' === $trimmedPathinfo) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_simple_trailing_slash_GET_method;
}
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'simple_trailing_slash_GET_method');
}
return array('_route' => 'simple_trailing_slash_GET_method');
}
not_simple_trailing_slash_GET_method:
// simple_trailing_slash_HEAD_method
if ('/trailing/simple/head-method' === $trimmedPathinfo) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_simple_trailing_slash_HEAD_method;
}
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'simple_trailing_slash_HEAD_method');
}
return array('_route' => 'simple_trailing_slash_HEAD_method');
}
not_simple_trailing_slash_HEAD_method:
// simple_trailing_slash_POST_method
if ('/trailing/simple/post-method/' === $pathinfo) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_simple_trailing_slash_POST_method;
}
return array('_route' => 'simple_trailing_slash_POST_method');
}
not_simple_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/trailing/regex')) {
// regex_trailing_slash_no_methods
if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) {
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'regex_trailing_slash_no_methods');
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ());
}
// regex_trailing_slash_GET_method
if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_regex_trailing_slash_GET_method;
}
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'regex_trailing_slash_GET_method');
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ());
}
not_regex_trailing_slash_GET_method:
// regex_trailing_slash_HEAD_method
if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_regex_trailing_slash_HEAD_method;
}
if (substr($pathinfo, -1) !== '/') {
return $this->redirect($pathinfo.'/', 'regex_trailing_slash_HEAD_method');
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ());
}
not_regex_trailing_slash_HEAD_method:
// regex_trailing_slash_POST_method
if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_regex_trailing_slash_POST_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ());
}
not_regex_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/not-trailing/simple')) {
// simple_not_trailing_slash_no_methods
if ('/not-trailing/simple/no-methods' === $pathinfo) {
return array('_route' => 'simple_not_trailing_slash_no_methods');
}
// simple_not_trailing_slash_GET_method
if ('/not-trailing/simple/get-method' === $pathinfo) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_simple_not_trailing_slash_GET_method;
}
return array('_route' => 'simple_not_trailing_slash_GET_method');
}
not_simple_not_trailing_slash_GET_method:
// simple_not_trailing_slash_HEAD_method
if ('/not-trailing/simple/head-method' === $pathinfo) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_simple_not_trailing_slash_HEAD_method;
}
return array('_route' => 'simple_not_trailing_slash_HEAD_method');
}
not_simple_not_trailing_slash_HEAD_method:
// simple_not_trailing_slash_POST_method
if ('/not-trailing/simple/post-method' === $pathinfo) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_simple_not_trailing_slash_POST_method;
}
return array('_route' => 'simple_not_trailing_slash_POST_method');
}
not_simple_not_trailing_slash_POST_method:
}
elseif (0 === strpos($pathinfo, '/not-trailing/regex')) {
// regex_not_trailing_slash_no_methods
if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ());
}
// regex_not_trailing_slash_GET_method
if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('GET' !== $canonicalMethod) {
$allow[] = 'GET';
goto not_regex_not_trailing_slash_GET_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ());
}
not_regex_not_trailing_slash_GET_method:
// regex_not_trailing_slash_HEAD_method
if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('HEAD' !== $requestMethod) {
$allow[] = 'HEAD';
goto not_regex_not_trailing_slash_HEAD_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ());
}
not_regex_not_trailing_slash_HEAD_method:
// regex_not_trailing_slash_POST_method
if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) {
if ('POST' !== $canonicalMethod) {
$allow[] = 'POST';
goto not_regex_not_trailing_slash_POST_method;
}
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ());
}
not_regex_not_trailing_slash_POST_method:
}
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
}
}

View File

@ -345,12 +345,33 @@ class PhpMatcherDumperTest extends TestCase
$groupOptimisedCollection->add('slashed_b', new Route('/slashed/group/b/'));
$groupOptimisedCollection->add('slashed_c', new Route('/slashed/group/c/'));
$trailingSlashCollection = new RouteCollection();
$trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', array(), array(), array(), '', array(), array()));
$trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', array(), array(), array(), '', array(), array('GET')));
$trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', array(), array(), array(), '', array(), array('HEAD')));
$trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', array(), array(), array(), '', array(), array('POST')));
$trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', array(), array(), array(), '', array(), array()));
$trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', array(), array(), array(), '', array(), array('GET')));
$trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', array(), array(), array(), '', array(), array('HEAD')));
$trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', array(), array(), array(), '', array(), array('POST')));
$trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', array(), array(), array(), '', array(), array()));
$trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', array(), array(), array(), '', array(), array('GET')));
$trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', array(), array(), array(), '', array(), array('HEAD')));
$trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', array(), array(), array(), '', array(), array('POST')));
$trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', array(), array(), array(), '', array(), array()));
$trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', array(), array(), array(), '', array(), array('GET')));
$trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', array(), array(), array(), '', array(), array('HEAD')));
$trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', array(), array(), array(), '', array(), array('POST')));
return array(
array($collection, 'url_matcher1.php', array()),
array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')),
array($rootprefixCollection, 'url_matcher3.php', array()),
array($headMatchCasesCollection, 'url_matcher4.php', array()),
array($groupOptimisedCollection, 'url_matcher5.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')),
array($trailingSlashCollection, 'url_matcher6.php', array()),
array($trailingSlashCollection, 'url_matcher7.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')),
);
}
}

View File

@ -476,7 +476,7 @@ EOTXT
*/
public function testBuggyRefs()
{
if (PHP_VERSION_ID >= 50600) {
if (\PHP_VERSION_ID >= 50600) {
$this->markTestSkipped('PHP 5.6 fixed refs counting');
}