diff --git a/.travis.yml b/.travis.yml index 5e8436f831284..70e364f8f960d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,7 @@ before_install: # A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line - if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi - if [[ ! $PHP = hhvm* ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi + - if [[ ! $skip ]]; then echo date.timezone = Europe/Paris >> $INI_FILE; fi - if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi - if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi - if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index e05a5f9bf7142..c6f63e1b6c2b5 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,28 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.20 (2016-10-27) + + * bug #20289 Fix edge case with StreamedResponse where headers are sent twice (Nicofuma) + * bug #20278 [DependencyInjection] merge tags instead of completely replacing them (xabbuh) + * bug #20271 Changes related to Twig 1.27 (fabpot) + * bug #20252 Trim constant values in XmlFileLoader (lstrojny) + * bug #20253 [TwigBridge] Use non-deprecated Twig_Node::getTemplateLine() (fabpot) + * bug #20235 [DomCrawler] Allow pipe (|) character in link tags when using Xpath expressions (klausi, nicolas-grekas) + * bug #20224 [Twig] removed deprecations added in Twig 1.27 (fabpot) + * bug #19478 fixed Filesystem:makePathRelative and added 2 more testcases (muhammedeminakbulut) + * bug #20218 [HttpFoundation] no 304 response if method is not cacheable (xabbuh) + * bug #20207 [DependencyInjection] move tags from decorated to decorating service (xabbuh) + * bug #20205 [HttpCache] fix: do not cache OPTIONS request (dmaicher) + * bug #20146 [Validator] Prevent infinite loop in PropertyMetadata (wesleylancel) + * bug #20184 [FrameworkBundle] Convert null prefix to an empty string in translation:update (chalasr) + * bug #19725 [Security] $attributes can be anything, but RoleVoter assumes strings (Jonatan Männchen) + * bug #20127 [HttpFoundation] JSONP callback validation (ro0NL) + * bug #20163 add missing use statement (xabbuh) + * bug #19961 [Console] Escape question text and default value in SymfonyStyle::ask() (chalasr) + * bug #20141 [Console] Fix validation of empty values using SymfonyQuestionHelper::ask() (chalasr) + * bug #20147 [FrameworkBundle] Alter container class instead of kernel name in cache:clear command (nicolas-grekas) + * 2.7.19 (2016-10-03) * bug #20102 [Validator] Url validator not validating hosts ending in a number (gwkunze) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 8f0a5d2bd6bf9..e5ad3abf25202 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,28 @@ in 2.8 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.8.0...v2.8.1 +* 2.8.14 (2016-11-21) + + * bug #20543 [DI] Fix error when trying to resolve a DefinitionDecorator (nicolas-grekas) + * bug #20544 [PhpUnitBridge] Fix time-sensitive tests that use data providers (julienfalque) + * bug #20484 bumped min version of Twig to 1.28 (fabpot) + * bug #20519 [Debug] Remove GLOBALS from exception context to avoid endless recursion (Seldaek) + * bug #20455 [ClassLoader] Fix ClassCollectionLoader inlining with __halt_compiler (giosh94mhz) + * bug #20307 [Form] Fix Date\TimeType marked as invalid on request with single_text and zero seconds (LuisDeimos) + * bug #20466 [Translation] fixed nested fallback catalogue using multiple locales. (aitboudad) + * bug #20465 [#18637][TranslationDebug] workaround for getFallbackLocales. (aitboudad) + * bug #20440 [TwigBridge][TwigBundle][HttpKernel] prefer getSourceContext() over getSource() (xabbuh) + * bug #20422 [Translation][fallback] add missing resources in parent catalogues. (aitboudad) + * bug #20378 [Form] Fixed show float values as choice value in ChoiceType (yceruto) + * bug #20294 Improved the design of the metrics in the profiler (javiereguiluz) + * bug #20375 [HttpFoundation][Session] Fix memcache session handler (klandaika) + * bug #20377 [Console] Fix infinite loop on missing input (chalasr) + * bug #20372 [Console] simplified code (fabpot) + * bug #20342 [Form] Fix UrlType transforms valid protocols (ogizanagi) + * bug #20292 Enhance GAE compat by removing some realpath() (nicolas-grekas) + * bug #20326 [VarDumper] Fix dumping Twig source in stack traces (nicolas-grekas) + * bug #20321 Compatibility with Twig 1.27 (xkobal) + * 2.8.13 (2016-10-27) * bug #20289 Fix edge case with StreamedResponse where headers are sent twice (Nicofuma) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index b0646cc1303cd..41c883159c8e2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -33,8 +33,8 @@ Symfony is the result of the work of many people who made the code better - Igor Wiedler (igorw) - Grégoire Pineau (lyrixx) - Eriksen Costa (eriksencosta) - - Sarah Khalil (saro0h) - Jules Pietri (heah) + - Sarah Khalil (saro0h) - Maxime Steinhausser (ogizanagi) - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) @@ -49,13 +49,13 @@ Symfony is the result of the work of many people who made the code better - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - Diego Saint Esteben (dii3g0) + - Robin Chalas (chalas_r) - Ener-Getick (energetick) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - Peter Rehm (rpet) - Iltar van der Berg (kjarli) - - Robin Chalas (chalas_r) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) @@ -69,6 +69,7 @@ Symfony is the result of the work of many people who made the code better - Henrik Westphal (snc) - Dariusz Górecki (canni) - Douglas Greenshields (shieldo) + - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) @@ -76,7 +77,6 @@ Symfony is the result of the work of many people who made the code better - Titouan Galopin (tgalopin) - Daniel Holmes (dholmes) - Pierre du Plessis (pierredup) - - Konstantin Myakshin (koc) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - John Wards (johnwards) @@ -84,17 +84,19 @@ Symfony is the result of the work of many people who made the code better - Fran Moreno (franmomu) - Antoine Hérault (herzult) - Paráda József (paradajozsef) + - Jáchym Toušek (enumag) - Arnaud Le Blanc (arnaud-lb) - Jérôme Tamarelle (gromnan) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - Dariusz Ruminski - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - - Dariusz Ruminski - marc.weistroff - Issei Murasawa (issei_m) - lenar - Włodzimierz Gajda (gajdaw) + - Roland Franssen (ro0) - Baptiste Clavié (talus) - Alexander Schwenn (xelaris) - Florian Voutzinos (florianv) @@ -104,8 +106,6 @@ Symfony is the result of the work of many people who made the code better - Peter Kokot (maastermedia) - excelwebzone - Jacob Dreesen (jdreesen) - - Jáchym Toušek (enumag) - - Roland Franssen (ro0) - Jérémy DERUSSÉ (jderusse) - Vladimir Reznichenko (kalessil) - Tomáš Votruba (tomas_votruba) @@ -131,6 +131,7 @@ Symfony is the result of the work of many people who made the code better - Andréia Bohner (andreia) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) + - jwdeitch - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) - Vyacheslav Pavlov @@ -139,6 +140,7 @@ Symfony is the result of the work of many people who made the code better - Thomas Rabaix (rande) - Vincent AUBERT (vincent) - Rouven Weßling (realityking) + - Teoh Han Hui (teohhanhui) - Mikael Pajunen - Clemens Tolboom - Helmer Aaviksoo @@ -149,7 +151,6 @@ Symfony is the result of the work of many people who made the code better - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba - - Teoh Han Hui (teohhanhui) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -159,10 +160,12 @@ Symfony is the result of the work of many people who made the code better - Richard Miller (mr_r_miller) - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) + - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) + - Lars Strojny (lstrojny) - Yonel Ceruto González (yonelceruto) - Stepan Anchugov (kix) - bronze1man @@ -185,13 +188,11 @@ Symfony is the result of the work of many people who made the code better - Michele Orselli (orso) - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - - Lars Strojny (lstrojny) - Rui Marinho (ruimarinho) - Daniel Espendiller - Dawid Nowak - Eugene Wissner - Julien Brochet (mewt) - - jeremyFreeAgent (jeremyfreeagent) - Sergey Linnik (linniksa) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) @@ -226,6 +227,7 @@ Symfony is the result of the work of many people who made the code better - Jakub Kucharovic (jkucharovic) - Eugene Leonovich (rybakit) - Filippo Tessarotto + - Tristan Darricau (nicofuma) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -262,7 +264,6 @@ Symfony is the result of the work of many people who made the code better - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - Daniel Wehner - - Tristan Darricau (nicofuma) - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) @@ -387,6 +388,7 @@ Symfony is the result of the work of many people who made the code better - Ariel Ferrandini (aferrandini) - Dirk Pahl (dirkaholic) - cedric lombardot (cedriclombardot) + - David Maicher (dmaicher) - Jonas Flodén (flojon) - Christian Schmidt - Marcin Sikoń (marphi) @@ -535,6 +537,7 @@ Symfony is the result of the work of many people who made the code better - Daisuke Ohata - Vincent Simonin - Alex Bogomazov (alebo) + - maxime.steinhausser - Stefan Warman - Tristan Maindron (tmaindron) - Ke WANG (yktd26) @@ -546,11 +549,11 @@ Symfony is the result of the work of many people who made the code better - Ulumuddin Yunus (joenoez) - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) + - Michael Devery (mickadoo) - Antoine Corcy - Artur Eshenbrener - Arturs Vonda - Sascha Grossenbacher - - David Maicher (dmaicher) - Szijarto Tamas - Catalin Dan - Stephan Vock @@ -593,6 +596,7 @@ Symfony is the result of the work of many people who made the code better - Vladyslav Petrovych - Alex Xandra Albert Sim - Carson Full + - Andrey Astakhov (aast) - Trent Steel (trsteel88) - Yuen-Chi Lian - Besnik Br @@ -602,12 +606,14 @@ Symfony is the result of the work of many people who made the code better - avorobiev - Venu - Lars Vierbergen + - Jonatan Männchen - Dennis Hotson - Andrew Tchircoff (andrewtch) - michaelwilliams - 1emming - Victor Bocharsky (bocharsky_bw) - Leevi Graham (leevigraham) + - Jordan Deitch - Casper Valdemar Poulsen - Josiah (josiah) - Joschi Kuphal @@ -740,6 +746,7 @@ Symfony is the result of the work of many people who made the code better - Alexandru Furculita (afurculita) - Ben Ramsey (ramsey) - Christian Jul Jensen + - Alexandre GESLIN (alexandregeslin) - The Whole Life to Learn - Farhad Safarov - Liverbool (liverbool) @@ -870,12 +877,14 @@ Symfony is the result of the work of many people who made the code better - James Gilliland - Rhodri Pugh (rodnaph) - David de Boer (ddeboer) + - Klaus Purer - Gilles Doge (gido) - abulford - antograssiot - Brooks Boyd - Roger Webb - Dmitriy Simushev + - Ivo Bathke (ivoba) - Max Voloshin (maxvoloshin) - Nicolas Fabre (nfabre) - Raul Rodriguez (raul782) @@ -964,7 +973,6 @@ Symfony is the result of the work of many people who made the code better - ChrisC - Ilya Biryukov - Kim Laï Trinh - - Jonatan Männchen - Jason Desrosiers - m.chwedziak - Philip Frank @@ -994,7 +1002,6 @@ Symfony is the result of the work of many people who made the code better - Emmanuel Vella (emmanuel.vella) - Carsten Nielsen (phreaknerd) - Mathieu Rochette - - maxime.steinhausser - Jay Severson - René Kerner - Nathaniel Catchpole @@ -1044,7 +1051,6 @@ Symfony is the result of the work of many people who made the code better - Benjamin Bender - Konrad Mohrfeldt - Lance Chen - - Andrey Astakhov (aast) - Andrew (drew) - Nikolay Labinskiy (e-moe) - kor3k kor3k (kor3k) @@ -1055,6 +1061,7 @@ Symfony is the result of the work of many people who made the code better - Mephistofeles - Hoffmann András - Olivier + - Wesley Lancel - pscheit - Zdeněk Drahoš - Dan Harper @@ -1160,6 +1167,7 @@ Symfony is the result of the work of many people who made the code better - JakeFr - Simon Sargeant - efeen + - Muhammed Akbulut - Michał Dąbrowski (defrag) - Simone Fumagalli (hpatoio) - Brian Graham (incognito) @@ -1176,6 +1184,7 @@ Symfony is the result of the work of many people who made the code better - Artem Lopata (bumz) - Nicole Cordes - Alexey Popkov + - Gijs Kunze - Artyom Protaskin - Nathanael d. Noblet - helmer @@ -1445,6 +1454,7 @@ Symfony is the result of the work of many people who made the code better - Matthias Althaus - Michaël VEROUX - Julia + - Lin Lu - arduanov - sualko - Nicolas Roudaire diff --git a/UPGRADE-2.7.md b/UPGRADE-2.7.md index 5de67ebede36c..1cf3d3df7f4dc 100644 --- a/UPGRADE-2.7.md +++ b/UPGRADE-2.7.md @@ -40,7 +40,7 @@ Form ---- * In form types and extension overriding the "setDefaultOptions" of the - AbstractType or AbstractExtensionType has been deprecated in favor of + AbstractType or AbstractTypeExtension has been deprecated in favor of overriding the new "configureOptions" method. The method "setDefaultOptions(OptionsResolverInterface $resolver)" will diff --git a/UPGRADE-2.8.md b/UPGRADE-2.8.md index 957f35b505cff..1d299af3e63a4 100644 --- a/UPGRADE-2.8.md +++ b/UPGRADE-2.8.md @@ -628,7 +628,7 @@ HttpFoundation After: ```php - $request->query->get('foo')[bar]; + $request->query->get('foo')['bar']; ``` Routing @@ -657,4 +657,9 @@ Routing // url generated in @router service $router->generate('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL); - ``` \ No newline at end of file + ``` + +DoctrineBridge +-------------- + * Deprecated using the entity provider with a Doctrine repository implementing `UserProviderInterface`. + Make it implement `UserLoaderInterface` instead. diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index 68e3780d8ab36..d5b4842eb7a72 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -202,6 +202,9 @@ UPGRADE FROM 2.x to 3.0 closures, but the closure is now resolved in the type instead of in the loader. + * Using the entity provider with a Doctrine repository implementing `UserProviderInterface` is not supported anymore. + You should make the repository implement `UserLoaderInterface` instead. + ### EventDispatcher * The interface `Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface` @@ -1750,5 +1753,5 @@ UPGRADE FROM 2.x to 3.0 After: ```php - $request->query->get('foo')[bar]; + $request->query->get('foo')['bar']; ``` diff --git a/appveyor.yml b/appveyor.yml index 69f51f8e7d068..cf7e664bb6dd6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ install: - cd .. - copy /Y php.ini-development php.ini-min - echo max_execution_time=1200 >> php.ini-min - - echo date.timezone="UTC" >> php.ini-min + - echo date.timezone="America/Los_Angeles" >> php.ini-min - echo extension_dir=ext >> php.ini-min - copy /Y php.ini-min php.ini-max - echo extension=php_openssl.dll >> php.ini-max diff --git a/composer.json b/composer.json index 1c95016073c22..261d4b25c4629 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.9", "doctrine/common": "~2.4", - "twig/twig": "~1.27|~2.0", + "twig/twig": "~1.28|~2.0", "psr/log": "~1.0", "symfony/security-acl": "~2.7|~3.0.0", "symfony/polyfill-apcu": "~1.1", diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 4d8c44701dd3a..71a2707bab709 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +2.8.0 +----- + + * deprecated using the entity provider with a Doctrine repository implementing UserProviderInterface + * added UserLoaderInterface for loading users through Doctrine. + 2.7.0 ----- diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index e1cbbbfb1a36e..940ca6fdf9fbd 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -134,10 +134,7 @@ protected function setMappingDriverConfig(array $mappingConfig, $mappingName) throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName)); } - if (substr($mappingDirectory, 0, 7) !== 'phar://') { - $mappingDirectory = realpath($mappingDirectory); - } - $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = $mappingDirectory; + $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingDirectory) ?: $mappingDirectory; } /** diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php index 96f05eb5b60c9..f8382ed2ebfb8 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php @@ -61,7 +61,7 @@ private function updateValidatorMappingFiles(ContainerBuilder $container, $mappi foreach ($container->getParameter('kernel.bundles') as $bundle) { $reflection = new \ReflectionClass($bundle); if (is_file($file = dirname($reflection->getFileName()).'/'.$validationPath)) { - $files[] = realpath($file); + $files[] = $file; $container->addResource(new FileResource($file)); } } diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index e24c1968854be..b943c142e8a28 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -138,7 +138,6 @@ public function configureOptions(OptionsResolver $resolver) $type = $this; $choiceLoader = function (Options $options) use ($choiceListFactory, &$choiceLoaders, $type) { - // Unless the choices are given explicitly, load them on demand if (null === $options['choices']) { $hash = null; diff --git a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php index 2882fd6ddd523..f67b4c9c3c8ac 100644 --- a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php @@ -55,7 +55,7 @@ public function loadUserByUsername($username) throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, get_class($repository))); } - @trigger_error('Implementing loadUserByUsername from Symfony\Component\Security\Core\User\UserProviderInterface is deprecated since version 2.8 and will be removed in 3.0. Implement the Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface instead.', E_USER_DEPRECATED); + @trigger_error('Implementing Symfony\Component\Security\Core\User\UserProviderInterface in a Doctrine repository when using the entity provider is deprecated since version 2.8 and will not be supported in 3.0. Make the repository implement Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface instead.', E_USER_DEPRECATED); } $user = $repository->loadUserByUsername($username); diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index 760c0fada0fab..f917f73eaa15b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -44,7 +44,7 @@ protected function setUp() $this->extension->expects($this->any()) ->method('getObjectManagerElementName') ->will($this->returnCallback(function ($name) { - return 'doctrine.orm.'.$name; + return 'doctrine.orm.'.$name; })); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php index a4c1a77152a75..56d590b109b2c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php @@ -81,6 +81,7 @@ public function testLoadUserByUsernameWithUserLoaderRepositoryAndWithoutProperty /** * @group legacy + * @expectedDeprecation Implementing Symfony\Component\Security\Core\User\UserProviderInterface in a Doctrine repository when using the entity provider is deprecated since version 2.8 and will not be supported in 3.0. Make the repository implement Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface instead. */ public function testLoadUserByUsernameWithUserProviderRepositoryAndWithoutProperty() { diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index 646a9c2e6f1dd..5e34792f9c0f1 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -134,7 +134,7 @@ public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $ti public function startTest(\PHPUnit_Framework_Test $test) { if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) { - $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName()); + $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false)); if (in_array('time-sensitive', $groups, true)) { ClockMock::register(get_class($test)); @@ -146,7 +146,7 @@ public function startTest(\PHPUnit_Framework_Test $test) public function endTest(\PHPUnit_Framework_Test $test, $time) { if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) { - $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName()); + $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false)); if (in_array('time-sensitive', $groups, true)) { ClockMock::withClockMock(false); diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index a18b817870f5e..44e23902e03de 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -61,7 +61,7 @@ protected function configure() new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), )) ->setDescription('Shows a list of twig functions, filters, globals and tests') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command outputs a list of twig functions, filters, globals and tests. Output can be filtered with an optional argument. diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index ab826456f7677..29a0d20421b25 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -62,7 +62,7 @@ protected function configure() ->setDescription('Lints a template and outputs encountered errors') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->addArgument('filename', InputArgument::IS_ARRAY) - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command lints a template and outputs to STDOUT the first encountered syntax error. diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index b226d91adfe48..e64d6eae2347d 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -49,7 +49,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) return $node; } else { - $var = $env->getParser()->getVarName(); + $var = $this->getVarName(); $name = new \Twig_Node_Expression_AssignName($var, $node->getTemplateLine()); $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getTemplateLine())); @@ -123,4 +123,9 @@ private function isNamedArguments($arguments) return false; } + + private function getVarName() + { + return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); + } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php index 0235c4da327a0..e96bd4f9a3bef 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php @@ -36,7 +36,7 @@ public function testTrans($template, $expected, array $variables = array()) $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false)); $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector()))); - echo $twig->compile($twig->parse($twig->tokenize(new \Twig_Source($twig->getLoader()->getSource('index'), 'index'))))."\n\n"; + echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n"; $this->assertEquals($expected, $this->getTemplate($template)->render($variables)); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php index 5d8ea6f0868ab..035dc4f671431 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php @@ -80,7 +80,13 @@ public function testOneVar() } EOTXT; - $expected = preg_replace('/%(.*?)%/', PHP_VERSION_ID >= 50400 ? '(isset($context["$1"]) ? $context["$1"] : null)' : '$this->getContext($context, "$1")', $expected); + if (PHP_VERSION_ID >= 70000) { + $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); + } elseif (PHP_VERSION_ID >= 50400) { + $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); + } else { + $expected = preg_replace('/%(.*?)%/', '$this->getContext($context, "$1")', $expected); + } $this->assertSame($expected, $compiler->compile($node)->getSource()); } @@ -106,7 +112,14 @@ public function testMultiVars() } EOTXT; - $expected = preg_replace('/%(.*?)%/', PHP_VERSION_ID >= 50400 ? '(isset($context["$1"]) ? $context["$1"] : null)' : '$this->getContext($context, "$1")', $expected); + + if (PHP_VERSION_ID >= 70000) { + $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); + } elseif (PHP_VERSION_ID >= 50400) { + $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); + } else { + $expected = preg_replace('/%(.*?)%/', '$this->getContext($context, "$1")', $expected); + } $this->assertSame($expected, $compiler->compile($node)->getSource()); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index f407afdcd6968..590b9ef75c617 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -66,6 +66,10 @@ public function testCompile() protected function getVariableGetter($name) { + if (PHP_VERSION_ID >= 70000) { + return sprintf('($context["%s"] ?? null)', $name, $name); + } + if (PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index ad76e25e8ee7a..0a3d30bdd5e5e 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -263,6 +263,10 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() protected function getVariableGetter($name) { + if (PHP_VERSION_ID >= 70000) { + return sprintf('($context["%s"] ?? null)', $name, $name); + } + if (PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 032975a8f2897..cbd21fc46edd2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -39,6 +39,10 @@ public function testCompileStrict() protected function getVariableGetterWithoutStrictCheck($name) { + if (PHP_VERSION_ID >= 70000) { + return sprintf('($context["%s"] ?? null)', $name, $name); + } + if (PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } @@ -48,10 +52,14 @@ protected function getVariableGetterWithoutStrictCheck($name) protected function getVariableGetterWithStrictCheck($name) { - if (version_compare(\Twig_Environment::VERSION, '2.0.0-DEV', '>=')) { + if (\Twig_Environment::MAJOR_VERSION >= 2) { return sprintf('(isset($context["%s"]) || array_key_exists("%s", $context) ? $context["%s"] : $this->notFound("%s", 0))', $name, $name, $name, $name); } + if (PHP_VERSION_ID >= 70000) { + return sprintf('($context["%s"] ?? $this->getContext($context, "%s"))', $name, $name, $name); + } + if (PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : $this->getContext($context, "%s"))', $name, $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php index 917687ad34eee..950c4d0810db0 100644 --- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php +++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php @@ -64,7 +64,7 @@ public function extract($resource, MessageCatalogue $catalogue) if ($file instanceof SplFileInfo) { $e->setTemplateName($file->getRelativePathname()); } elseif ($file instanceof \SplFileInfo) { - $e->setTemplateName($file->getRealPath()); + $e->setTemplateName($file->getRealPath() ?: $file->getPathname()); } throw $e; diff --git a/src/Symfony/Bridge/Twig/TwigEngine.php b/src/Symfony/Bridge/Twig/TwigEngine.php index 3e3257e7fa0f5..1ac9d0102e63b 100644 --- a/src/Symfony/Bridge/Twig/TwigEngine.php +++ b/src/Symfony/Bridge/Twig/TwigEngine.php @@ -75,14 +75,14 @@ public function exists($name) $loader = $this->environment->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface) { + if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) { return $loader->exists((string) $name); } try { // cast possible TemplateReferenceInterface to string because the // EngineInterface supports them but Twig_LoaderInterface does not - $loader->getSource((string) $name); + $loader->getSourceContext((string) $name)->getCode(); } catch (\Twig_Error_Loader $e) { return false; } diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 746da0a05a065..f7c36adc5721a 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.9", - "twig/twig": "~1.27|~2.0" + "twig/twig": "~1.28|~2.0" }, "require-dev": { "symfony/asset": "~2.7|~3.0.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 0433e19768c46..87bd4413ae0ea 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -39,7 +39,7 @@ protected function configure() new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), )) ->setDescription('Dumps the current configuration for an extension') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command dumps the current configuration for an extension/bundle. diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index 9732537362f1e..2eb310ddf1701 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -39,7 +39,7 @@ protected function configure() new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), )) ->setDescription('Displays configured listeners for an application') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command displays all configured listeners: php %command.full_name% diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php index fdec77788d952..5e2f273ac8784 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php @@ -41,7 +41,7 @@ protected function configure() )) ->setName('server:start') ->setDescription('Starts PHP built-in web server in the background') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% runs PHP's built-in web server: php %command.full_name% diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php index 9ce6c3b15e841..8f79978a9a845 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php @@ -36,7 +36,7 @@ protected function configure() )) ->setName('server:stop') ->setDescription('Stops PHP\'s built-in web server that was started with the server:start command') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% stops PHP's built-in web server: php %command.full_name% diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index 59b6743a59caf..4404f3a0f6963 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -21,6 +21,8 @@ use Symfony\Component\Translation\Catalogue\MergeOperation; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Translator; +use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Component\Translation\LoggingTranslator; /** * Helps finding unused or missing translation messages in a given locale @@ -53,7 +55,7 @@ protected function configure() new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), )) ->setDescription('Displays translation messages information') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command helps finding unused or missing translation messages and comparing them with the fallback ones by inspecting the templates and translation files of a given bundle or the app folder. @@ -301,7 +303,7 @@ private function loadFallbackCatalogues($locale, $transPaths, TranslationLoader { $fallbackCatalogues = array(); $translator = $this->getContainer()->get('translator'); - if ($translator instanceof Translator) { + if ($translator instanceof Translator || $translator instanceof DataCollectorTranslator || $translator instanceof LoggingTranslator) { foreach ($translator->getFallbackLocales() as $fallbackLocale) { if ($fallbackLocale === $locale) { continue; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 64874e70ef2cc..72298480b4e31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -119,9 +119,8 @@ protected function execute(InputInterface $input, OutputInterface $output) // load any messages from templates $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); $io->comment('Parsing templates...'); - $prefix = $input->getOption('prefix'); $extractor = $this->getContainer()->get('translation.extractor'); - $extractor->setPrefix(null === $prefix ? '' : $prefix); + $extractor->setPrefix($input->getOption('prefix')); foreach ($transPaths as $path) { $path .= 'views'; if (is_dir($path)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index e3c750d6d00e3..72229961b4fd0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -35,7 +35,7 @@ protected function configure() ->setDescription('Lints a file and outputs encountered errors') ->addArgument('filename', null, 'A file or a directory or STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') - ->setHelp(<<setHelp(<<<'EOF' The %command.name% command lints a YAML file and outputs to STDOUT the first encountered syntax error. diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3bb72fb374da8..66cbe99aeb3ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -52,7 +52,7 @@ class FrameworkExtension extends Extension */ public function load(array $configs, ContainerBuilder $container) { - $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader = new XmlFileLoader($container, new FileLocator(dirname(__DIR__).'/Resources/config')); $loader->load('web.xml'); $loader->load('services.xml'); @@ -693,7 +693,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) { $r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException'); - $dirs[] = dirname($r->getFileName()).'/../Resources/translations'; + $dirs[] = dirname(dirname($r->getFileName())).'/Resources/translations'; } $rootDir = $container->getParameter('kernel.root_dir'); foreach ($container->getParameter('kernel.bundles') as $bundle => $class) { @@ -824,21 +824,21 @@ private function getValidatorMappingFiles(ContainerBuilder $container) $dirname = dirname($reflection->getFileName()); if (is_file($file = $dirname.'/Resources/config/validation.xml')) { - $files[0][] = realpath($file); + $files[0][] = $file; $container->addResource(new FileResource($file)); } if (is_file($file = $dirname.'/Resources/config/validation.yml')) { - $files[1][] = realpath($file); + $files[1][] = $file; $container->addResource(new FileResource($file)); } if (is_dir($dir = $dirname.'/Resources/config/validation')) { foreach (Finder::create()->files()->in($dir)->name('*.xml') as $file) { - $files[0][] = $file->getRealPath(); + $files[0][] = $file->getPathname(); } foreach (Finder::create()->files()->in($dir)->name('*.yml') as $file) { - $files[1][] = $file->getRealPath(); + $files[1][] = $file->getPathname(); } $container->addResource(new DirectoryResource($dir)); @@ -946,7 +946,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $dirname = dirname($reflection->getFileName()); if (is_file($file = $dirname.'/Resources/config/serialization.xml')) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array(realpath($file))); + $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file)); $definition->setPublic(false); $serializerLoaders[] = $definition; @@ -954,7 +954,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder } if (is_file($file = $dirname.'/Resources/config/serialization.yml')) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array(realpath($file))); + $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file)); $definition->setPublic(false); $serializerLoaders[] = $definition; @@ -963,13 +963,13 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder if (is_dir($dir = $dirname.'/Resources/config/serialization')) { foreach (Finder::create()->files()->in($dir)->name('*.xml') as $file) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getRealPath())); + $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getPathname())); $definition->setPublic(false); $serializerLoaders[] = $definition; } foreach (Finder::create()->files()->in($dir)->name('*.yml') as $file) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file->getRealPath())); + $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file->getPathname())); $definition->setPublic(false); $serializerLoaders[] = $definition; @@ -1042,7 +1042,7 @@ private function getKernelRootHash(ContainerBuilder $container) */ public function getXsdValidationBasePath() { - return __DIR__.'/../Resources/config/schema'; + return dirname(__DIR__).'/Resources/config/schema'; } public function getNamespace() diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php index 324eb4782c2cc..bf4a4c478502b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/number_widget.html.php @@ -1 +1 @@ -block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php index 4390687a69330..ec96cfb46b24c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/password_widget.html.php @@ -1 +1 @@ -block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'password')) ?> +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'password')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php index 59b29f4cbcfaa..8519da429b188 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/percent_widget.html.php @@ -1 +1 @@ -block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> % +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> % diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/reset_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/reset_widget.html.php index 1575e8292801e..e8fa18e488df8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/reset_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/reset_widget.html.php @@ -1 +1 @@ -block($form, 'button_widget', array('type' => isset($type) ? $type : 'reset')) ?> +block($form, 'button_widget', array('type' => isset($type) ? $type : 'reset')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php index 4e442f6ef47ae..48a33f4aa2dbc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/search_widget.html.php @@ -1 +1 @@ -block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'search')) ?> +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'search')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/submit_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/submit_widget.html.php index d42bb2a78ffe9..6bf71f5a1e1c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/submit_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/submit_widget.html.php @@ -1 +1 @@ -block($form, 'button_widget', array('type' => isset($type) ? $type : 'submit')) ?> +block($form, 'button_widget', array('type' => isset($type) ? $type : 'submit')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php index 0ce4ed2ca79fd..9e26318497b3c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/url_widget.html.php @@ -1 +1 @@ -block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'url')) ?> +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'url')) ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index c0b68a2d17a46..4ef5f0a4bd1c4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -164,7 +164,6 @@ private function resolve($value) gettype($resolved) ) ); - }, $value); return str_replace('%%', '%', $escapedValue); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 3c1728575081e..3dc64a300e8c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -88,7 +88,6 @@ private function getContainer() ->will($this->returnValueMap(array( array('router', 1, $router), array('controller_name_converter', 1, $loader), - ))); return $container; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index c99c0ace2ac77..27f61c4383f24 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -136,7 +136,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('extract') ->will( $this->returnCallback(function ($path, $catalogue) use ($extractedMessages) { - $catalogue->add($extractedMessages); + $catalogue->add($extractedMessages); }) ); @@ -146,7 +146,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('loadMessages') ->will( $this->returnCallback(function ($path, $catalogue) use ($loadedMessages) { - $catalogue->add($loadedMessages); + $catalogue->add($loadedMessages); }) ); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index 40eab748c62bf..536c59fae4709 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -91,7 +91,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('extract') ->will( $this->returnCallback(function ($path, $catalogue) use ($extractedMessages) { - $catalogue->add($extractedMessages); + $catalogue->add($extractedMessages); }) ); @@ -101,7 +101,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('loadMessages') ->will( $this->returnCallback(function ($path, $catalogue) use ($loadedMessages) { - $catalogue->add($loadedMessages); + $catalogue->add($loadedMessages); }) ); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php index a0b12504bb2d3..1dc4ff6aab4ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -146,6 +146,7 @@ public function getDescribeCallableTestData() } abstract protected function getDescriptor(); + abstract protected function getFormat(); private function assertDescription($expectedDescription, $describedObject, array $options = array()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index 36931a4f96fb6..20c223a135f1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -191,9 +191,11 @@ class CallableClass public function __invoke() { } + public static function staticMethod() { } + public function method() { } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index fe892c5483488..f5c9aa8e6a61e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -371,11 +371,11 @@ public function testValidationPaths() // Testing symfony/framework-bundle with deps=high $this->assertStringEndsWith('symfony'.DIRECTORY_SEPARATOR.'form/Resources/config/validation.xml', $xmlMappings[0]); } - $this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.xml', $xmlMappings[1]); + $this->assertStringEndsWith('TestBundle/Resources/config/validation.xml', $xmlMappings[1]); $yamlMappings = $calls[4][1][0]; $this->assertCount(1, $yamlMappings); - $this->assertStringEndsWith('TestBundle'.DIRECTORY_SEPARATOR.'Resources'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'validation.yml', $yamlMappings[0]); + $this->assertStringEndsWith('TestBundle/Resources/config/validation.yml', $yamlMappings[0]); } public function testValidationNoStaticMethod() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php index 04df261863f48..c0ae6ec5c6604 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php @@ -1,7 +1,7 @@ This template is used for translation message extraction tests trans('single-quoted key') ?> trans('double-quoted key') ?> -trans(<<trans(<<<'EOF' heredoc key EOF ) ?> diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 707c6338b9455..e99b4242082de 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -99,7 +99,7 @@ public function collect(Request $request, Response $response, \Exception $except 'token_class' => get_class($token), 'logout_url' => $logoutUrl, 'user' => $token->getUsername(), - 'roles' => array_map(function (RoleInterface $role) { return $role->getRole();}, $assignedRoles), + 'roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles), 'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles), 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index c85c3df907c38..55f09c48373b5 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -430,11 +430,10 @@ private function addEncodersSection(ArrayNodeDefinition $rootNode) ->children() ->arrayNode('encoders') ->example(array( - 'Acme\DemoBundle\Entity\User1' => 'sha512', - 'Acme\DemoBundle\Entity\User2' => array( - 'algorithm' => 'sha512', - 'encode_as_base64' => 'true', - 'iterations' => 5000, + 'AppBundle\Entity\User1' => 'bcrypt', + 'AppBundle\Entity\User2' => array( + 'algorithm' => 'bcrypt', + 'cost' => 13, ), )) ->requiresAtLeastOneElement() diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php index 2b3310c61aae4..028e885246f61 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SecurityFactoryInterface.php @@ -25,7 +25,7 @@ interface SecurityFactoryInterface * Configures the container services required to use the authentication listener. * * @param ContainerBuilder $container - * @param string $id The unique id of the firewall + * @param string $id The unique id of the firewall * @param array $config The options array for the listener * @param string $userProvider The service id of the user provider * @param string $defaultEntryPoint @@ -48,7 +48,7 @@ public function getPosition(); /** * Defines the configuration key used to reference the provider * in the firewall configuration. - * + * * @return string */ public function getKey(); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index eb22424dac676..49c836d8853d3 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -31,13 +31,13 @@ "symfony/framework-bundle": "~2.8", "symfony/http-foundation": "~2.4|~3.0.0", "symfony/twig-bundle": "~2.7|~3.1.0", - "symfony/twig-bridge": "~2.7|~3.1.0", + "symfony/twig-bridge": "~2.7,>=2.7.4|~3.1.0", "symfony/process": "~2.0,>=2.0.5|~3.0.0", "symfony/validator": "~2.5|~3.0.0", "symfony/yaml": "~2.0,>=2.0.5|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", "doctrine/doctrine-bundle": "~1.2", - "twig/twig": "~1.27|~2.0" + "twig/twig": "~1.28|~2.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\SecurityBundle\\": "" }, diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 47bb19380d285..1fcfbd94027cc 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -129,12 +129,12 @@ protected function templateExists($template) $template = (string) $template; $loader = $this->twig->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface) { + if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) { return $loader->exists($template); } try { - $loader->getSource($template); + $loader->getSourceContext($template)->getCode(); return true; } catch (\Twig_Error_Loader $e) { diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php index 4e0bef365ebbb..53fe300e29a62 100644 --- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php @@ -58,6 +58,7 @@ public function exists($name) * Otherwise the template is located using the locator from the twig library. * * @param string|TemplateReferenceInterface $template The template + * @param bool $throw When true, a \Twig_Error_Loader exception will be thrown if a template could not be found * * @return string The path to the template file * @@ -87,7 +88,11 @@ protected function findTemplate($template, $throw = true) } if (false === $file || null === $file) { - throw $twigLoaderException; + if ($throw) { + throw $twigLoaderException; + } + + return false; } return $this->cache[$logicalName] = $file; diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/PreviewErrorControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/PreviewErrorControllerTest.php index 7bef647a7e283..e4a47a07694b5 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/PreviewErrorControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/PreviewErrorControllerTest.php @@ -34,7 +34,6 @@ public function testForwardRequestToConfiguredController() ->method('handle') ->with( $this->callback(function (Request $request) use ($self, $logicalControllerName, $code) { - $self->assertEquals($logicalControllerName, $request->attributes->get('_controller')); $exception = $request->attributes->get('exception'); diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php index 9804c08a1923b..64ba490388f9f 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php @@ -115,4 +115,17 @@ public function testTwigErrorIfTemplateDoesNotExist() $method->setAccessible(true); $method->invoke($loader, 'name.format.engine'); } + + public function testTwigSoftErrorIfTemplateDoesNotExist() + { + $parser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface'); + $locator = $this->getMock('Symfony\Component\Config\FileLocatorInterface'); + + $loader = new FilesystemLoader($locator, $parser); + $loader->addPath(__DIR__.'/../DependencyInjection/Fixtures/Resources/views'); + + $method = new \ReflectionMethod('Symfony\Bundle\TwigBundle\Loader\FilesystemLoader', 'findTemplate'); + $method->setAccessible(true); + $this->assertFalse($method->invoke($loader, 'name.format.engine', false)); + } } diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 14dc1b037af81..2ccc47952fad1 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -21,7 +21,7 @@ "symfony/twig-bridge": "~2.7|~3.0.0", "symfony/http-foundation": "~2.5|~3.0.0", "symfony/http-kernel": "~2.7", - "twig/twig": "~1.27|~2.0" + "twig/twig": "~1.28|~2.0" }, "require-dev": { "symfony/stopwatch": "~2.2|~3.0.0", diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 6d37caf4f11dc..4e6f15bd01ee5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -110,7 +110,7 @@ public function panelAction(Request $request, $token) 'panel' => $panel, 'page' => $page, 'request' => $request, - 'templates' => $this->getTemplateManager()->getTemplates($profile), + 'templates' => $this->getTemplateManager()->getNames($profile), 'is_ajax' => $request->isXmlHttpRequest(), 'profiler_markup_version' => 2, // 1 = original profiler, 2 = Symfony 2.8+ profiler )), 200, array('Content-Type' => 'text/html')); @@ -210,7 +210,7 @@ public function toolbarAction(Request $request, $token) 'request' => $request, 'position' => $position, 'profile' => $profile, - 'templates' => $this->getTemplateManager()->getTemplates($profile), + 'templates' => $this->getTemplateManager()->getNames($profile), 'profiler_url' => $url, 'token' => $token, 'profiler_markup_version' => 2, // 1 = original toolbar, 2 = Symfony 2.8+ toolbar diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index b0181afe87c12..696687fe019f9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -67,7 +67,9 @@ public function getName(Profile $profile, $panel) * * @param Profile $profile * - * @return array + * @return Twig_Template[] + * + * @deprecated not used anymore internally */ public function getTemplates(Profile $profile) { @@ -89,7 +91,7 @@ public function getTemplates(Profile $profile) * * @throws \UnexpectedValueException */ - protected function getNames(Profile $profile) + public function getNames(Profile $profile) { $templates = array(); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index 98ea6c3265d2a..6860230243106 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -60,10 +60,19 @@ Symfony initialization + {% if profile.collectors.memory %} +
+ {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MB + Peak memory usage +
+ {% endif %} + {% if profile.children|length > 0 %} +
+
{{ profile.children|length }} - Sub-Requests + Sub-Request{{ profile.children|length > 1 ? 's' }}
{% set subrequests_time = 0 %} @@ -73,14 +82,7 @@
{{ subrequests_time }} ms - Sub-Requests time -
- {% endif %} - - {% if profile.collectors.memory %} -
- {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MB - Peak memory usage + Sub-Request{{ profile.children|length > 1 ? 's' }} time
{% endif %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig index e2bc8f8013443..868ff051c9c79 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig @@ -71,7 +71,11 @@ {% if templates is defined %}