diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
index ca85d8aba5994..4279995ec91ca 100644
--- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
+++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php
@@ -19,6 +19,7 @@
class DeprecationErrorHandler
{
const MODE_WEAK = 'weak';
+ const MODE_WEAK_VENDORS = 'weak_vendors';
const MODE_DISABLED = 'disabled';
private static $isRegistered = false;
@@ -28,6 +29,7 @@ class DeprecationErrorHandler
*
* The following reporting modes are supported:
* - use "weak" to hide the deprecation report but keep a global count;
+ * - use "weak_vendors" to act as "weak" but only for vendors;
* - use "/some-regexp/" to stop the test suite whenever a deprecation
* message matches the given regular expression;
* - use a number to define the upper bound of allowed deprecations,
@@ -41,6 +43,8 @@ public static function register($mode = 0)
return;
}
+ $UtilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
+
$getMode = function () use ($mode) {
static $memoizedMode = false;
@@ -50,40 +54,71 @@ public static function register($mode = 0)
if (false === $mode) {
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
}
- if (DeprecationErrorHandler::MODE_WEAK !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
+ if (DeprecationErrorHandler::MODE_WEAK !== $mode && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
}
return $memoizedMode = $mode;
};
+ $inVendors = function ($path) {
+ /** @var string[] absolute paths to vendor directories */
+ static $vendors;
+ if (null === $vendors) {
+ foreach (get_declared_classes() as $class) {
+ if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
+ $r = new \ReflectionClass($class);
+ $v = dirname(dirname($r->getFileName()));
+ if (file_exists($v.'/composer/installed.json')) {
+ $vendors[] = $v;
+ }
+ }
+ }
+ }
+ $path = realpath($path) ?: $path;
+ foreach ($vendors as $vendor) {
+ if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
$deprecations = array(
'unsilencedCount' => 0,
'remainingCount' => 0,
'legacyCount' => 0,
'otherCount' => 0,
+ 'remaining vendorCount' => 0,
'unsilenced' => array(),
'remaining' => array(),
'legacy' => array(),
'other' => array(),
+ 'remaining vendor' => array(),
);
- $deprecationHandler = function ($type, $msg, $file, $line, $context) use (&$deprecations, $getMode) {
+ $deprecationHandler = function ($type, $msg, $file, $line, $context) use (&$deprecations, $getMode, $UtilPrefix, $inVendors) {
$mode = $getMode();
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode) {
- return \PHPUnit_Util_ErrorHandler::handleError($type, $msg, $file, $line, $context);
+ $ErrorHandler = $UtilPrefix.'ErrorHandler';
+
+ return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
}
$trace = debug_backtrace(true);
$group = 'other';
+ $isWeak = DeprecationErrorHandler::MODE_WEAK === $mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = $inVendors($file));
+
$i = count($trace);
- while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_')))) {
+ while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
// No-op
}
if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
$class = isset($trace[$i]['object']) ? get_class($trace[$i]['object']) : $trace[$i]['class'];
$method = $trace[$i]['function'];
+ $Test = $UtilPrefix.'Test';
if (0 !== error_reporting()) {
$group = 'unsilenced';
@@ -91,9 +126,11 @@ public static function register($mode = 0)
|| 0 === strpos($method, 'provideLegacy')
|| 0 === strpos($method, 'getLegacy')
|| strpos($class, '\Legacy')
- || in_array('legacy', \PHPUnit_Util_Test::getGroups($class, $method), true)
+ || in_array('legacy', $Test::getGroups($class, $method), true)
) {
$group = 'legacy';
+ } elseif (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor) {
+ $group = 'remaining vendor';
} else {
$group = 'remaining';
}
@@ -112,13 +149,13 @@ public static function register($mode = 0)
exit(1);
}
- if ('legacy' !== $group && DeprecationErrorHandler::MODE_WEAK !== $mode) {
+ if ('legacy' !== $group && !$isWeak) {
$ref = &$deprecations[$group][$msg]['count'];
++$ref;
$ref = &$deprecations[$group][$msg][$class.'::'.$method];
++$ref;
}
- } elseif (DeprecationErrorHandler::MODE_WEAK !== $mode) {
+ } elseif (!$isWeak) {
$ref = &$deprecations[$group][$msg]['count'];
++$ref;
}
@@ -128,7 +165,7 @@ public static function register($mode = 0)
if (null !== $oldErrorHandler) {
restore_error_handler();
- if (array('PHPUnit_Util_ErrorHandler', 'handleError') === $oldErrorHandler) {
+ if (array($UtilPrefix.'ErrorHandler', 'handleError') === $oldErrorHandler) {
restore_error_handler();
self::register($mode);
}
@@ -141,7 +178,7 @@ public static function register($mode = 0)
return "\x1B[{$color}m{$str}\x1B[0m";
};
} else {
- $colorize = function ($str) {return $str;};
+ $colorize = function ($str) { return $str; };
}
register_shutdown_function(function () use ($getMode, &$deprecations, $deprecationHandler, $colorize) {
$mode = $getMode();
@@ -152,7 +189,7 @@ public static function register($mode = 0)
restore_error_handler();
if (DeprecationErrorHandler::MODE_WEAK === $mode) {
- $colorize = function ($str) {return $str;};
+ $colorize = function ($str) { return $str; };
}
if ($currErrorHandler !== $deprecationHandler) {
echo "\n", $colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n";
@@ -162,9 +199,18 @@ public static function register($mode = 0)
return $b['count'] - $a['count'];
};
- foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) {
+ $groups = array('unsilenced', 'remaining');
+ if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode) {
+ $groups[] = 'remaining vendor';
+ }
+ array_push($groups, 'legacy', 'other');
+
+ foreach ($groups as $group) {
if ($deprecations[$group.'Count']) {
- echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n";
+ echo "\n", $colorize(
+ sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']),
+ 'legacy' !== $group && 'remaining vendor' !== $group
+ ), "\n";
uasort($deprecations[$group], $cmp);
diff --git a/src/Symfony/Bridge/PhpUnit/LICENSE b/src/Symfony/Bridge/PhpUnit/LICENSE
index 39fa189d2b5fc..207646a052dcd 100644
--- a/src/Symfony/Bridge/PhpUnit/LICENSE
+++ b/src/Symfony/Bridge/PhpUnit/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014-2016 Fabien Potencier
+Copyright (c) 2014-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/Command.php b/src/Symfony/Bridge/PhpUnit/Legacy/Command.php
new file mode 100644
index 0000000000000..0aec8ab67f33e
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/Command.php
@@ -0,0 +1,28 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PhpUnit\Legacy;
+
+/**
+ * {@inheritdoc}
+ *
+ * @internal
+ */
+class Command extends \PHPUnit_TextUI_Command
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function createRunner()
+ {
+ return new TestRunner($this->arguments['loader']);
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php
new file mode 100644
index 0000000000000..5ed545a5127cc
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php
@@ -0,0 +1,59 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PhpUnit\Legacy;
+
+/**
+ * Collects and replays skipped tests.
+ *
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener
+{
+ private $trait;
+
+ public function __construct(array $mockedNamespaces = array())
+ {
+ $this->trait = new SymfonyTestsListenerTrait($mockedNamespaces);
+ }
+
+ public function globalListenerDisabled()
+ {
+ $this->trait->globalListenerDisabled();
+ }
+
+ public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
+ {
+ return $this->trait->startTestSuite($suite);
+ }
+
+ public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+ {
+ return $this->trait->addSkippedTest($test, $e, $time);
+ }
+
+ public function startTest(\PHPUnit_Framework_Test $test)
+ {
+ return $this->trait->startTest($test);
+ }
+
+ public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time)
+ {
+ return $this->trait->addWarning($test, $e, $time);
+ }
+
+ public function endTest(\PHPUnit_Framework_Test $test, $time)
+ {
+ return $this->trait->endTest($test, $time);
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php
new file mode 100644
index 0000000000000..f8814c3c844a7
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php
@@ -0,0 +1,319 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PhpUnit\Legacy;
+
+use Doctrine\Common\Annotations\AnnotationRegistry;
+use PHPUnit\Framework\AssertionFailedError;
+use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Util\Blacklist;
+use PHPUnit\Util\Test;
+use Symfony\Bridge\PhpUnit\ClockMock;
+use Symfony\Bridge\PhpUnit\DnsMock;
+
+/**
+ * PHP 5.3 compatible trait-like shared implementation.
+ *
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+class SymfonyTestsListenerTrait
+{
+ private static $globallyEnabled = false;
+ private $state = -1;
+ private $skippedFile = false;
+ private $wasSkipped = array();
+ private $isSkipped = array();
+ private $expectedDeprecations = array();
+ private $gatheredDeprecations = array();
+ private $previousErrorHandler;
+ private $testsWithWarnings;
+ private $reportUselessTests;
+ private $error;
+
+ /**
+ * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive)
+ */
+ public function __construct(array $mockedNamespaces = array())
+ {
+ if (class_exists('PHPUnit_Util_Blacklist')) {
+ \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\DeprecationErrorHandler'] = 1;
+ \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\SymfonyTestsListener'] = 1;
+ \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener'] = 1;
+ \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait'] = 1;
+ } else {
+ Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\DeprecationErrorHandler'] = 1;
+ Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\SymfonyTestsListener'] = 1;
+ Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait'] = 1;
+ }
+
+ $warn = false;
+ foreach ($mockedNamespaces as $type => $namespaces) {
+ if (!is_array($namespaces)) {
+ $namespaces = array($namespaces);
+ }
+ if (is_int($type)) {
+ // @deprecated BC with v2.8 to v3.0
+ $type = 'time-sensitive';
+ $warn = true;
+ }
+ if ('time-sensitive' === $type) {
+ foreach ($namespaces as $ns) {
+ ClockMock::register($ns.'\DummyClass');
+ }
+ }
+ if ('dns-sensitive' === $type) {
+ foreach ($namespaces as $ns) {
+ DnsMock::register($ns.'\DummyClass');
+ }
+ }
+ }
+ if (self::$globallyEnabled) {
+ $this->state = -2;
+ } else {
+ self::$globallyEnabled = true;
+ if ($warn) {
+ echo "Clock-mocked namespaces for SymfonyTestsListener need to be nested in a \"time-sensitive\" key. This will be enforced in Symfony 4.0.\n";
+ }
+ }
+ }
+
+ public function __destruct()
+ {
+ if (0 < $this->state) {
+ file_put_contents($this->skippedFile, 'isSkipped, true).';');
+ }
+ }
+
+ public function globalListenerDisabled()
+ {
+ self::$globallyEnabled = false;
+ $this->state = -1;
+ }
+
+ public function startTestSuite($suite)
+ {
+ if (class_exists('PHPUnit_Util_Blacklist', false)) {
+ $Test = 'PHPUnit_Util_Test';
+ } else {
+ $Test = 'PHPUnit\Util\Test';
+ }
+ $suiteName = $suite->getName();
+ $this->testsWithWarnings = array();
+
+ if (-1 === $this->state) {
+ echo "Testing $suiteName\n";
+ $this->state = 0;
+
+ if (!class_exists('Doctrine\Common\Annotations\AnnotationRegistry', false) && class_exists('Doctrine\Common\Annotations\AnnotationRegistry')) {
+ AnnotationRegistry::registerLoader('class_exists');
+ }
+
+ if ($this->skippedFile = getenv('SYMFONY_PHPUNIT_SKIPPED_TESTS')) {
+ $this->state = 1;
+
+ if (file_exists($this->skippedFile)) {
+ $this->state = 2;
+
+ if (!$this->wasSkipped = require $this->skippedFile) {
+ echo "All tests already ran successfully.\n";
+ $suite->setTests(array());
+ }
+ }
+ }
+ $testSuites = array($suite);
+ for ($i = 0; isset($testSuites[$i]); ++$i) {
+ foreach ($testSuites[$i]->tests() as $test) {
+ if ($test instanceof \PHPUnit_Framework_TestSuite || $test instanceof TestSuite) {
+ if (!class_exists($test->getName(), false)) {
+ $testSuites[] = $test;
+ continue;
+ }
+ $groups = $Test::getGroups($test->getName());
+ if (in_array('time-sensitive', $groups, true)) {
+ ClockMock::register($test->getName());
+ }
+ if (in_array('dns-sensitive', $groups, true)) {
+ DnsMock::register($test->getName());
+ }
+ }
+ }
+ }
+ } elseif (2 === $this->state) {
+ $skipped = array();
+ foreach ($suite->tests() as $test) {
+ if (!($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)
+ || isset($this->wasSkipped[$suiteName]['*'])
+ || isset($this->wasSkipped[$suiteName][$test->getName()])) {
+ $skipped[] = $test;
+ }
+ }
+ $suite->setTests($skipped);
+ }
+ }
+
+ public function addSkippedTest($test, \Exception $e, $time)
+ {
+ if (0 < $this->state) {
+ if ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) {
+ $class = get_class($test);
+ $method = $test->getName();
+ } else {
+ $class = $test->getName();
+ $method = '*';
+ }
+
+ $this->isSkipped[$class][$method] = 1;
+ }
+ }
+
+ public function startTest($test)
+ {
+ if (-2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) {
+ if (null !== $test->getTestResultObject()) {
+ $this->reportUselessTests = $test->getTestResultObject()->isStrictAboutTestsThatDoNotTestAnything();
+ }
+
+ if (class_exists('PHPUnit_Util_Blacklist', false)) {
+ $Test = 'PHPUnit_Util_Test';
+ $AssertionFailedError = 'PHPUnit_Framework_AssertionFailedError';
+ } else {
+ $Test = 'PHPUnit\Util\Test';
+ $AssertionFailedError = 'PHPUnit\Framework\AssertionFailedError';
+ }
+ $groups = $Test::getGroups(get_class($test), $test->getName(false));
+
+ if (in_array('time-sensitive', $groups, true)) {
+ ClockMock::register(get_class($test));
+ ClockMock::withClockMock(true);
+ }
+ if (in_array('dns-sensitive', $groups, true)) {
+ DnsMock::register(get_class($test));
+ }
+
+ $annotations = $Test::parseTestMethodAnnotations(get_class($test), $test->getName(false));
+
+ if (isset($annotations['class']['expectedDeprecation'])) {
+ $test->getTestResultObject()->addError($test, new $AssertionFailedError('`@expectedDeprecation` annotations are not allowed at the class level.'), 0);
+ }
+ if (isset($annotations['method']['expectedDeprecation'])) {
+ if (!in_array('legacy', $groups, true)) {
+ $this->error = new $AssertionFailedError('Only tests with the `@group legacy` annotation can have `@expectedDeprecation`.');
+ }
+
+ $test->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(false);
+
+ $this->expectedDeprecations = $annotations['method']['expectedDeprecation'];
+ $this->previousErrorHandler = set_error_handler(array($this, 'handleError'));
+ }
+ }
+ }
+
+ public function addWarning($test, $e, $time)
+ {
+ if ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) {
+ $this->testsWithWarnings[$test->getName()] = true;
+ }
+ }
+
+ public function endTest($test, $time)
+ {
+ if (class_exists('PHPUnit_Util_Blacklist', false)) {
+ $Test = 'PHPUnit_Util_Test';
+ $BaseTestRunner = 'PHPUnit_Runner_BaseTestRunner';
+ $Warning = 'PHPUnit_Framework_Warning';
+ } else {
+ $Test = 'PHPUnit\Util\Test';
+ $BaseTestRunner = 'PHPUnit\Runner\BaseTestRunner';
+ $Warning = 'PHPUnit\Framework\Warning';
+ }
+ $className = get_class($test);
+ $classGroups = $Test::getGroups($className);
+ $groups = $Test::getGroups($className, $test->getName(false));
+
+ if (null !== $this->reportUselessTests) {
+ $test->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything($this->reportUselessTests);
+ $this->reportUselessTests = null;
+ }
+
+ $errored = false;
+
+ if (null !== $this->error) {
+ if ($BaseTestRunner::STATUS_PASSED === $test->getStatus()) {
+ $test->getTestResultObject()->addError($test, $this->error, 0);
+ $errored = true;
+ }
+
+ $this->error = null;
+ }
+
+ if ($this->expectedDeprecations) {
+ if (!in_array($test->getStatus(), array($BaseTestRunner::STATUS_SKIPPED, $BaseTestRunner::STATUS_INCOMPLETE), true)) {
+ $test->addToAssertionCount(count($this->expectedDeprecations));
+ }
+
+ restore_error_handler();
+
+ if (!$errored && !in_array($test->getStatus(), array($BaseTestRunner::STATUS_SKIPPED, $BaseTestRunner::STATUS_INCOMPLETE, $BaseTestRunner::STATUS_FAILURE, $BaseTestRunner::STATUS_ERROR), true)) {
+ try {
+ $prefix = "@expectedDeprecation:\n";
+ $test->assertStringMatchesFormat($prefix.'%A '.implode("\n%A ", $this->expectedDeprecations)."\n%A", $prefix.' '.implode("\n ", $this->gatheredDeprecations)."\n");
+ } catch (AssertionFailedError $e) {
+ $test->getTestResultObject()->addFailure($test, $e, $time);
+ } catch (\PHPUnit_Framework_AssertionFailedError $e) {
+ $test->getTestResultObject()->addFailure($test, $e, $time);
+ }
+ }
+
+ $this->expectedDeprecations = $this->gatheredDeprecations = array();
+ $this->previousErrorHandler = null;
+ }
+ if (-2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) {
+ if (in_array('time-sensitive', $groups, true)) {
+ ClockMock::withClockMock(false);
+ }
+ if (in_array('dns-sensitive', $groups, true)) {
+ DnsMock::withMockedHosts(array());
+ }
+ }
+
+ if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) && 0 === strpos($test->getName(), 'testLegacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $groups, true)) {
+ $result = $test->getTestResultObject();
+
+ if (method_exists($result, 'addWarning')) {
+ $result->addWarning($test, new $Warning('Using the "testLegacy" prefix to mark tests as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time);
+ }
+ }
+
+ if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) && strpos($className, '\Legacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $classGroups, true)) {
+ $result = $test->getTestResultObject();
+
+ if (method_exists($result, 'addWarning')) {
+ $result->addWarning($test, new $Warning('Using the "Legacy" prefix to mark all tests of a class as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time);
+ }
+ }
+ }
+
+ public function handleError($type, $msg, $file, $line, $context)
+ {
+ if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
+ $h = $this->previousErrorHandler;
+
+ return $h ? $h($type, $msg, $file, $line, $context) : false;
+ }
+ if (error_reporting()) {
+ $msg = 'Unsilenced deprecation: '.$msg;
+ }
+ $this->gatheredDeprecations[] = $msg;
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php
new file mode 100644
index 0000000000000..4bbf2f1cb9724
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/TestRunner.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PhpUnit\Legacy;
+
+/**
+ * {@inheritdoc}
+ *
+ * @internal
+ */
+class TestRunner extends \PHPUnit_TextUI_TestRunner
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function handleConfiguration(array &$arguments)
+ {
+ $listener = new SymfonyTestsListener();
+
+ $result = parent::handleConfiguration($arguments);
+
+ $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array();
+
+ $registeredLocally = false;
+
+ foreach ($arguments['listeners'] as $registeredListener) {
+ if ($registeredListener instanceof SymfonyTestsListener) {
+ $registeredListener->globalListenerDisabled();
+ $registeredLocally = true;
+ break;
+ }
+ }
+
+ if (!$registeredLocally) {
+ $arguments['listeners'][] = $listener;
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php
index 0d873732636a9..f85dbb367ca9c 100644
--- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php
+++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php
@@ -11,201 +11,60 @@
namespace Symfony\Bridge\PhpUnit;
-use Doctrine\Common\Annotations\AnnotationRegistry;
+use PHPUnit\Framework\BaseTestListener;
+use PHPUnit\Framework\Test;
+use PHPUnit\Framework\TestSuite;
+use PHPUnit\Framework\Warning;
+
+if (class_exists('PHPUnit_Framework_BaseTestListener')) {
+ class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener');
+
+ return;
+}
/**
* Collects and replays skipped tests.
*
* @author Nicolas Grekas
+ *
+ * @final
*/
-class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener
+class SymfonyTestsListener extends BaseTestListener
{
- private static $globallyEnabled = false;
- private $state = -1;
- private $skippedFile = false;
- private $wasSkipped = array();
- private $isSkipped = array();
- private $expectedDeprecations = array();
- private $gatheredDeprecations = array();
- private $previousErrorHandler;
+ private $trait;
- /**
- * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive)
- */
public function __construct(array $mockedNamespaces = array())
{
- $warn = false;
- foreach ($mockedNamespaces as $type => $namespaces) {
- if (!is_array($namespaces)) {
- $namespaces = array($namespaces);
- }
- if (is_int($type)) {
- // @deprecated BC with v2.8 to v3.0
- $type = 'time-sensitive';
- $warn = true;
- }
- if ('time-sensitive' === $type) {
- foreach ($namespaces as $ns) {
- ClockMock::register($ns.'\DummyClass');
- }
- }
- if ('dns-sensitive' === $type) {
- foreach ($namespaces as $ns) {
- DnsMock::register($ns.'\DummyClass');
- }
- }
- }
- if (self::$globallyEnabled) {
- $this->state = -2;
- } else {
- self::$globallyEnabled = true;
- if ($warn) {
- echo "Clock-mocked namespaces for SymfonyTestsListener need to be nested in a \"time-sensitive\" key. This will be enforced in Symfony 4.0.\n";
- }
- }
+ $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces);
}
- public function __destruct()
+ public function globalListenerDisabled()
{
- if (0 < $this->state) {
- file_put_contents($this->skippedFile, 'isSkipped, true).';');
- }
+ $this->trait->globalListenerDisabled();
}
- public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
+ public function startTestSuite(TestSuite $suite)
{
- $suiteName = $suite->getName();
-
- if (-1 === $this->state) {
- echo "Testing $suiteName\n";
- $this->state = 0;
-
- if (!class_exists('Doctrine\Common\Annotations\AnnotationRegistry', false) && class_exists('Doctrine\Common\Annotations\AnnotationRegistry')) {
- AnnotationRegistry::registerLoader('class_exists');
- }
-
- if ($this->skippedFile = getenv('SYMFONY_PHPUNIT_SKIPPED_TESTS')) {
- $this->state = 1;
-
- if (file_exists($this->skippedFile)) {
- $this->state = 2;
-
- if (!$this->wasSkipped = require $this->skippedFile) {
- echo "All tests already ran successfully.\n";
- $suite->setTests(array());
- }
- }
- }
- $testSuites = array($suite);
- for ($i = 0; isset($testSuites[$i]); ++$i) {
- foreach ($testSuites[$i]->tests() as $test) {
- if ($test instanceof \PHPUnit_Framework_TestSuite) {
- if (!class_exists($test->getName(), false)) {
- $testSuites[] = $test;
- continue;
- }
- $groups = \PHPUnit_Util_Test::getGroups($test->getName());
- if (in_array('time-sensitive', $groups, true)) {
- ClockMock::register($test->getName());
- }
- if (in_array('dns-sensitive', $groups, true)) {
- DnsMock::register($test->getName());
- }
- }
- }
- }
- } elseif (2 === $this->state) {
- $skipped = array();
- foreach ($suite->tests() as $test) {
- if (!$test instanceof \PHPUnit_Framework_TestCase
- || isset($this->wasSkipped[$suiteName]['*'])
- || isset($this->wasSkipped[$suiteName][$test->getName()])) {
- $skipped[] = $test;
- }
- }
- $suite->setTests($skipped);
- }
+ return $this->trait->startTestSuite($suite);
}
- public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
+ public function addSkippedTest(Test $test, \Exception $e, $time)
{
- if (0 < $this->state) {
- if ($test instanceof \PHPUnit_Framework_TestCase) {
- $class = get_class($test);
- $method = $test->getName();
- } else {
- $class = $test->getName();
- $method = '*';
- }
-
- $this->isSkipped[$class][$method] = 1;
- }
+ return $this->trait->addSkippedTest($test, $e, $time);
}
- public function startTest(\PHPUnit_Framework_Test $test)
+ public function startTest(Test $test)
{
- if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) {
- $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false));
-
- if (in_array('time-sensitive', $groups, true)) {
- ClockMock::register(get_class($test));
- ClockMock::withClockMock(true);
- }
- if (in_array('dns-sensitive', $groups, true)) {
- DnsMock::register(get_class($test));
- }
-
- $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($test), $test->getName(false));
-
- if (isset($annotations['class']['expectedDeprecation'])) {
- $test->getTestResultObject()->addError($test, new \PHPUnit_Framework_AssertionFailedError('`@expectedDeprecation` annotations are not allowed at the class level.'), 0);
- }
- if (isset($annotations['method']['expectedDeprecation'])) {
- if (!in_array('legacy', $groups, true)) {
- $test->getTestResultObject()->addError($test, new \PHPUnit_Framework_AssertionFailedError('Only tests with the `@group legacy` annotation can have `@expectedDeprecation`.'), 0);
- }
- $this->expectedDeprecations = $annotations['method']['expectedDeprecation'];
- $this->previousErrorHandler = set_error_handler(array($this, 'handleError'));
- }
- }
+ return $this->trait->startTest($test);
}
- public function endTest(\PHPUnit_Framework_Test $test, $time)
+ public function addWarning(Test $test, Warning $e, $time)
{
- if ($this->expectedDeprecations) {
- restore_error_handler();
- try {
- $prefix = "@expectedDeprecation:\n ";
- $test->assertStringMatchesFormat($prefix.implode("\n ", $this->expectedDeprecations), $prefix.implode("\n ", $this->gatheredDeprecations));
- } catch (\PHPUnit_Framework_AssertionFailedError $e) {
- $test->getTestResultObject()->addFailure($test, $e, $time);
- }
-
- $this->expectedDeprecations = $this->gatheredDeprecations = array();
- $this->previousErrorHandler = null;
- }
- if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) {
- $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false));
-
- if (in_array('time-sensitive', $groups, true)) {
- ClockMock::withClockMock(false);
- }
- if (in_array('dns-sensitive', $groups, true)) {
- DnsMock::withMockedHosts(array());
- }
- }
+ return $this->trait->addWarning($test, $e, $time);
}
- public function handleError($type, $msg, $file, $line, $context)
+ public function endTest(Test $test, $time)
{
- if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
- $h = $this->previousErrorHandler;
-
- return $h ? $h($type, $msg, $file, $line, $context) : false;
- }
- if (error_reporting()) {
- $msg = 'Unsilenced deprecation: '.$msg;
- }
- $this->gatheredDeprecations[] = $msg;
+ return $this->trait->endTest($test, $time);
}
}
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt
index fac5c53ae7486..cd733724870cd 100644
--- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt
+++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt
@@ -18,6 +18,19 @@ require_once __DIR__.'/../../bootstrap.php';
@trigger_error('root deprecation', E_USER_DEPRECATED);
+eval(<<<'EOPHP'
+namespace PHPUnit\Util;
+
+class Test
+{
+ public static function getGroups()
+ {
+ return array();
+ }
+}
+EOPHP
+);
+
class PHPUnit_Util_Test
{
public static function getGroups()
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php
new file mode 100644
index 0000000000000..6f5123d4feb0c
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php
@@ -0,0 +1,35 @@
+testLegacyFoo();
+$foo->testNonLegacyBar();
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php
new file mode 100644
index 0000000000000..bf315f2eaa312
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php
@@ -0,0 +1,3 @@
+testLegacyFoo();
+$foo->testNonLegacyBar();
+
+?>
+--EXPECTF--
+Unsilenced deprecation notices (3)
+
+unsilenced foo deprecation: 2x
+ 2x in FooTestCase::testLegacyFoo
+
+unsilenced bar deprecation: 1x
+ 1x in FooTestCase::testNonLegacyBar
+
+Remaining deprecation notices (1)
+
+silenced bar deprecation: 1x
+ 1x in FooTestCase::testNonLegacyBar
+
+Legacy deprecation notices (1)
+
+Other deprecation notices (1)
+
+root deprecation: 1x
+
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt
new file mode 100644
index 0000000000000..7bbda8775d6d5
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test DeprecationErrorHandler in weak vendors mode on vendor file
+--FILE--
+globalListenerDisabled();
+ $registeredLocally = true;
+ break;
+ }
+ }
+
+ if (!$registeredLocally) {
+ $arguments['listeners'][] = $listener;
+ }
+
+ return $result;
}
}
diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
index 9f846a3ecbaae..4683682a1bf6e 100755
--- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
+++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
@@ -16,7 +16,7 @@
error_reporting(-1);
// PHPUnit 4.8 does not support PHP 7, while 5.1 requires PHP 5.6+
-$PHPUNIT_VERSION = PHP_VERSION_ID >= 50600 ? getenv('SYMFONY_PHPUNIT_VERSION') ?: '5.3' : '4.8';
+$PHPUNIT_VERSION = PHP_VERSION_ID >= 50600 ? getenv('SYMFONY_PHPUNIT_VERSION') ?: '5.7' : '4.8';
$oldPwd = getcwd();
$PHPUNIT_DIR = getenv('SYMFONY_PHPUNIT_DIR') ?: (__DIR__.'/.phpunit');
$PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php';
@@ -37,12 +37,15 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
if (file_exists("phpunit-$PHPUNIT_VERSION")) {
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? '(del /S /F /Q %s & rmdir %1$s) >nul': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION"));
}
- if (extension_loaded('openssl') && ini_get('allow_url_fopen')) {
+ if (extension_loaded('openssl') && ini_get('allow_url_fopen') && !isset($_SERVER['http_proxy']) && !isset($_SERVER['https_proxy'])) {
stream_copy_to_stream(fopen("https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip", 'rb'), fopen("$PHPUNIT_VERSION.zip", 'wb'));
} else {
@unlink("$PHPUNIT_VERSION.zip");
passthru("wget https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip");
}
+ if (!class_exists('ZipArchive')) {
+ throw new \Exception('simple-phpunit requires the "zip" PHP extension to be installed and enabled in order to uncompress the downloaded PHPUnit packages.');
+ }
$zip = new ZipArchive();
$zip->open("$PHPUNIT_VERSION.zip");
$zip->extractTo(getcwd());
@@ -53,7 +56,10 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\"");
}
passthru("$COMPOSER require --no-update symfony/phpunit-bridge \">=3.2@dev\"");
- passthru("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", $exit);
+ $prevRoot = getenv('COMPOSER_ROOT_VERSION');
+ putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION");
+ $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true)));
+ putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : ''));
if ($exit) {
exit($exit);
}
@@ -180,27 +186,10 @@ if ($components) {
}
}
} elseif (!isset($argv[1]) || 'install' !== $argv[1] || file_exists('install')) {
- // Run regular phpunit in a subprocess
-
- $errFile = tempnam(sys_get_temp_dir(), 'phpunit.stderr.');
- if ($proc = proc_open(sprintf($cmd, '', ' 2> '.escapeshellarg($errFile)), array(1 => array('pipe', 'w')), $pipes)) {
- stream_copy_to_stream($pipes[1], STDOUT);
- fclose($pipes[1]);
- $exit = proc_close($proc);
-
- readfile($errFile);
- unlink($errFile);
- }
-
- if (!file_exists($component = array_pop($argv))) {
- $component = basename($oldPwd);
- }
-
- if ($exit) {
- echo "\033[41mKO\033[0m $component\n\n";
- } else {
- echo "\033[32mOK\033[0m $component\n\n";
- }
+ array_splice($argv, 1, 0, array('--colors=always'));
+ $_SERVER['argv'] = $argv;
+ $_SERVER['argc'] = ++$argc;
+ include "$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit";
}
exit($exit);
diff --git a/src/Symfony/Bridge/PhpUnit/bootstrap.php b/src/Symfony/Bridge/PhpUnit/bootstrap.php
index 5e2ed0ca85f82..f2ceffb1b51ae 100644
--- a/src/Symfony/Bridge/PhpUnit/bootstrap.php
+++ b/src/Symfony/Bridge/PhpUnit/bootstrap.php
@@ -13,7 +13,7 @@
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
// Detect if we're loaded by an actual run of phpunit
-if (!defined('PHPUNIT_COMPOSER_INSTALL') && !class_exists('PHPUnit_TextUI_Command', false)) {
+if (!defined('PHPUNIT_COMPOSER_INSTALL') && !class_exists('PHPUnit_TextUI_Command', false) && !class_exists('PHPUnit\TextUI\Command', false)) {
return;
}
diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json
index 1cf3ef04318e5..847bb691d3ad8 100644
--- a/src/Symfony/Bridge/PhpUnit/composer.json
+++ b/src/Symfony/Bridge/PhpUnit/composer.json
@@ -21,7 +21,11 @@
"php": ">=5.3.3"
},
"suggest": {
- "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
+ "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader",
+ "ext-zip": "Zip support is required when using bin/simple-phpunit"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
},
"autoload": {
"files": [ "bootstrap.php" ],
@@ -36,7 +40,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist b/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist
index 9b64b02947c0e..816cfe4927ed3 100644
--- a/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist
+++ b/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist
@@ -5,6 +5,8 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
diff --git a/src/Symfony/Bridge/ProxyManager/LICENSE b/src/Symfony/Bridge/ProxyManager/LICENSE
index 12a74531e40a4..17d16a13367dd 100644
--- a/src/Symfony/Bridge/ProxyManager/LICENSE
+++ b/src/Symfony/Bridge/ProxyManager/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2016 Fabien Potencier
+Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
index 3f3c577b846df..b634a69488a34 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
@@ -13,6 +13,7 @@
require_once __DIR__.'/Fixtures/includes/foo.php';
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -22,7 +23,7 @@
*
* @author Marco Pivetta
*/
-class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
+class ContainerBuilderTest extends TestCase
{
public function testCreateProxyServiceWithRuntimeInstantiator()
{
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php
index 789799bce6e19..a191901753d24 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\Dumper;
+use PHPUnit\Framework\TestCase;
use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -22,7 +23,7 @@
*
* @author Marco Pivetta
*/
-class PhpDumperTest extends \PHPUnit_Framework_TestCase
+class PhpDumperTest extends TestCase
{
public function testDumpContainerWithProxyService()
{
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php
index fe98c150f71a2..77e04571e089c 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php
@@ -122,9 +122,6 @@ public function __unset($name)
unset($this->valueHolder5157dd96e88c0->$name);
}
- /**
- *
- */
public function __clone()
{
$this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array());
@@ -132,9 +129,6 @@ public function __clone()
$this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0;
}
- /**
- *
- */
public function __sleep()
{
$this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array());
@@ -142,9 +136,6 @@ public function __sleep()
return array('valueHolder5157dd96e88c0');
}
- /**
- *
- */
public function __wakeup()
{
}
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php
index 12409e8e637bf..6787b9ff8ed45 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php
@@ -122,9 +122,6 @@ public function __unset($name)
unset($this->valueHolder5157dd96e88c0->$name);
}
- /**
- *
- */
public function __clone()
{
$this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array());
@@ -132,9 +129,6 @@ public function __clone()
$this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0;
}
- /**
- *
- */
public function __sleep()
{
$this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array());
@@ -142,9 +136,6 @@ public function __sleep()
return array('valueHolder5157dd96e88c0');
}
- /**
- *
- */
public function __wakeup()
{
}
@@ -168,7 +159,7 @@ public function getProxyInitializer()
/**
* {@inheritdoc}
*/
- public function initializeProxy() : bool
+ public function initializeProxy(): bool
{
return $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, 'initializeProxy', array());
}
@@ -176,7 +167,7 @@ public function initializeProxy() : bool
/**
* {@inheritdoc}
*/
- public function isProxyInitialized() : bool
+ public function isProxyInitialized(): bool
{
return null !== $this->valueHolder5157dd96e88c0;
}
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php
index 8b2402b045f28..e58b7d6356161 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Instantiator/RuntimeInstantiatorTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\Instantiator;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
use Symfony\Component\DependencyInjection\Definition;
@@ -19,7 +20,7 @@
*
* @author Marco Pivetta
*/
-class RuntimeInstantiatorTest extends \PHPUnit_Framework_TestCase
+class RuntimeInstantiatorTest extends TestCase
{
/**
* @var RuntimeInstantiator
@@ -37,7 +38,7 @@ protected function setUp()
public function testInstantiateProxy()
{
$instance = new \stdClass();
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$definition = new Definition('stdClass');
$instantiator = function () use ($instance) {
return $instance;
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
index 8b6555cfe2556..64082c8f7f3f1 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\DependencyInjection\Definition;
@@ -19,7 +20,7 @@
*
* @author Marco Pivetta
*/
-class ProxyDumperTest extends \PHPUnit_Framework_TestCase
+class ProxyDumperTest extends TestCase
{
/**
* @var ProxyDumper
diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json
index f6d0d22aed972..42751d000e59d 100644
--- a/src/Symfony/Bridge/ProxyManager/composer.json
+++ b/src/Symfony/Bridge/ProxyManager/composer.json
@@ -32,7 +32,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist
index 60980be9e531e..f280e037fec08 100644
--- a/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist
+++ b/src/Symfony/Bridge/ProxyManager/phpunit.xml.dist
@@ -5,6 +5,8 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
diff --git a/src/Symfony/Bridge/Twig/AppVariable.php b/src/Symfony/Bridge/Twig/AppVariable.php
index 02fe5e5b68526..e8e69d0ee3d68 100644
--- a/src/Symfony/Bridge/Twig/AppVariable.php
+++ b/src/Symfony/Bridge/Twig/AppVariable.php
@@ -145,4 +145,40 @@ public function getDebug()
return $this->debug;
}
+
+ /**
+ * Returns some or all the existing flash messages:
+ * * getFlashes() returns all the flash messages
+ * * getFlashes('notice') returns a simple array with flash messages of that type
+ * * getFlashes(array('notice', 'error')) returns a nested array of type => messages.
+ *
+ * @return array
+ */
+ public function getFlashes($types = null)
+ {
+ // needed to avoid starting the session automatically when looking for flash messages
+ try {
+ $session = $this->getSession();
+ if (null === $session || !$session->isStarted()) {
+ return array();
+ }
+ } catch (\RuntimeException $e) {
+ return array();
+ }
+
+ if (null === $types || '' === $types || array() === $types) {
+ return $session->getFlashBag()->all();
+ }
+
+ if (is_string($types)) {
+ return $session->getFlashBag()->get($types);
+ }
+
+ $result = array();
+ foreach ($types as $type) {
+ $result[$type] = $session->getFlashBag()->get($type);
+ }
+
+ return $result;
+ }
}
diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md
index 685e1c9b083f0..9c635c9508f29 100644
--- a/src/Symfony/Bridge/Twig/CHANGELOG.md
+++ b/src/Symfony/Bridge/Twig/CHANGELOG.md
@@ -1,12 +1,48 @@
CHANGELOG
=========
+3.3.0
+-----
+
+ * added a `workflow_has_marked_place` function
+ * added a `workflow_marked_places` function
+
3.2.0
-----
* added `AppVariable::getToken()`
- * Deprecated the possibility to inject the Form Twig Renderer into the form
- extension. Inject it on TwigRendererEngine instead.
+ * Deprecated the possibility to inject the Form `TwigRenderer` into the `FormExtension`.
+ * [BC BREAK] Registering the `FormExtension` without configuring a runtime loader for the `TwigRenderer`
+ doesn't work anymore.
+
+ Before:
+
+ ```php
+ use Symfony\Bridge\Twig\Extension\FormExtension;
+ use Symfony\Bridge\Twig\Form\TwigRenderer;
+ use Symfony\Bridge\Twig\Form\TwigRendererEngine;
+
+ // ...
+ $rendererEngine = new TwigRendererEngine(array('form_div_layout.html.twig'));
+ $rendererEngine->setEnvironment($twig);
+ $twig->addExtension(new FormExtension(new TwigRenderer($rendererEngine, $csrfTokenManager)));
+ ```
+
+ After:
+
+ ```php
+ // ...
+ $rendererEngine = new TwigRendererEngine(array('form_div_layout.html.twig'), $twig);
+ // require Twig 1.30+
+ $twig->addRuntimeLoader(new \Twig_FactoryRuntimeLoader(array(
+ TwigRenderer::class => function () use ($rendererEngine, $csrfTokenManager) {
+ return new TwigRenderer($rendererEngine, $csrfTokenManager);
+ },
+ )));
+ $twig->addExtension(new FormExtension());
+ ```
+ * Deprecated the `TwigRendererEngineInterface` interface.
+ * added WorkflowExtension (provides `workflow_can` and `workflow_transitions`)
2.7.0
-----
diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
index 44e23902e03de..4748444cd181f 100644
--- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php
+++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
@@ -87,9 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$twig = $this->getTwigEnvironment();
if (null === $twig) {
- $io->error('The Twig environment needs to be set.');
-
- return 1;
+ throw new \RuntimeException('The Twig environment needs to be set.');
}
$types = array('functions', 'filters', 'tests', 'globals');
@@ -140,7 +138,7 @@ private function getMetadata($type, $entity)
}
if ($type === 'functions' || $type === 'filters') {
$cb = $entity->getCallable();
- if (is_null($cb)) {
+ if (null === $cb) {
return;
}
if (is_array($cb)) {
diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php
index ebbfde12c2058..b252ee274cd57 100644
--- a/src/Symfony/Bridge/Twig/Command/LintCommand.php
+++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php
@@ -88,9 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io = new SymfonyStyle($input, $output);
if (null === $twig = $this->getTwigEnvironment()) {
- $io->error('The Twig environment needs to be set.');
-
- return 1;
+ throw new \RuntimeException('The Twig environment needs to be set.');
}
$filenames = $input->getArgument('filename');
diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php
index 90b21d0495ff7..f075709654c95 100644
--- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php
+++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php
@@ -93,7 +93,11 @@ public function getHtmlCallGraph()
public function getProfile()
{
if (null === $this->profile) {
- $this->profile = unserialize($this->data['profile']);
+ if (PHP_VERSION_ID >= 70000) {
+ $this->profile = unserialize($this->data['profile'], array('allowed_classes' => array('Twig_Profiler_Profile')));
+ } else {
+ $this->profile = unserialize($this->data['profile']);
+ }
}
return $this->profile;
diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php
index 016e6a9586c97..81a8683c35b97 100644
--- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php
@@ -13,6 +13,7 @@
use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
use Symfony\Bridge\Twig\Form\TwigRendererInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
/**
@@ -23,12 +24,17 @@
*/
class FormExtension extends \Twig_Extension implements \Twig_Extension_InitRuntimeInterface
{
+ /**
+ * @deprecated since version 3.2, to be removed in 4.0 alongside with magic methods below
+ */
private $renderer;
- public function __construct(TwigRendererInterface $renderer = null)
+ public function __construct($renderer = null)
{
- if (null !== $this->renderer) {
+ if ($renderer instanceof TwigRendererInterface) {
@trigger_error(sprintf('Passing a Twig Form Renderer to the "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0. Pass the Twig_Environment to the TwigRendererEngine constructor instead.', static::class), E_USER_DEPRECATED);
+ } elseif (null !== $renderer && !(is_array($renderer) && isset($renderer[0], $renderer[1]) && $renderer[0] instanceof ContainerInterface)) {
+ throw new \InvalidArgumentException(sprintf('Passing any arguments the constructor of %s is reserved for internal use.', __CLASS__));
}
$this->renderer = $renderer;
}
@@ -40,8 +46,10 @@ public function __construct(TwigRendererInterface $renderer = null)
*/
public function initRuntime(\Twig_Environment $environment)
{
- if (null !== $this->renderer) {
+ if ($this->renderer instanceof TwigRendererInterface) {
$this->renderer->setEnvironment($environment);
+ } elseif (null !== $this->renderer) {
+ $this->renderer[2] = $environment;
}
}
@@ -94,6 +102,62 @@ public function getTests()
);
}
+ /**
+ * @internal
+ */
+ public function __get($name)
+ {
+ if ('renderer' === $name) {
+ @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+
+ if (is_array($this->renderer)) {
+ $renderer = $this->renderer[0]->get($this->renderer[1]);
+ if (isset($this->renderer[2])) {
+ $renderer->setEnvironment($this->renderer[2]);
+ }
+ $this->renderer = $renderer;
+ }
+ }
+
+ return $this->$name;
+ }
+
+ /**
+ * @internal
+ */
+ public function __set($name, $value)
+ {
+ if ('renderer' === $name) {
+ @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+ }
+
+ $this->$name = $value;
+ }
+
+ /**
+ * @internal
+ */
+ public function __isset($name)
+ {
+ if ('renderer' === $name) {
+ @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+ }
+
+ return isset($this->$name);
+ }
+
+ /**
+ * @internal
+ */
+ public function __unset($name)
+ {
+ if ('renderer' === $name) {
+ @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+ }
+
+ unset($this->$name);
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php
index 7469183e75de1..81cef949c7408 100644
--- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php
@@ -40,11 +40,25 @@ public function getFunctions()
);
}
+ /**
+ * @param string $name
+ * @param array $parameters
+ * @param bool $relative
+ *
+ * @return string
+ */
public function getPath($name, $parameters = array(), $relative = false)
{
return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
}
+ /**
+ * @param string $name
+ * @param array $parameters
+ * @param bool $schemeRelative
+ *
+ * @return string
+ */
public function getUrl($name, $parameters = array(), $schemeRelative = false)
{
return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
diff --git a/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php
new file mode 100644
index 0000000000000..14e1fc2736bae
--- /dev/null
+++ b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php
@@ -0,0 +1,137 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\Twig\Extension;
+
+use Fig\Link\GenericLinkProvider;
+use Fig\Link\Link;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Twig extension for the Symfony WebLink component.
+ *
+ * @author Kévin Dunglas
+ */
+class WebLinkExtension extends \Twig_Extension
+{
+ private $requestStack;
+
+ public function __construct(RequestStack $requestStack)
+ {
+ $this->requestStack = $requestStack;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFunctions()
+ {
+ return array(
+ new \Twig_SimpleFunction('link', array($this, 'link')),
+ new \Twig_SimpleFunction('preload', array($this, 'preload')),
+ new \Twig_SimpleFunction('dns_prefetch', array($this, 'dnsPrefetch')),
+ new \Twig_SimpleFunction('preconnect', array($this, 'preconnect')),
+ new \Twig_SimpleFunction('prefetch', array($this, 'prefetch')),
+ new \Twig_SimpleFunction('prerender', array($this, 'prerender')),
+ );
+ }
+
+ /**
+ * Adds a "Link" HTTP header.
+ *
+ * @param string $uri The relation URI
+ * @param string $rel The relation type (e.g. "preload", "prefetch", "prerender" or "dns-prefetch")
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
+ *
+ * @return string The relation URI
+ */
+ public function link($uri, $rel, array $attributes = array())
+ {
+ if (!$request = $this->requestStack->getMasterRequest()) {
+ return $uri;
+ }
+
+ $link = new Link($rel, $uri);
+ foreach ($attributes as $key => $value) {
+ $link = $link->withAttribute($key, $value);
+ }
+
+ $linkProvider = $request->attributes->get('_links', new GenericLinkProvider());
+ $request->attributes->set('_links', $linkProvider->withLink($link));
+
+ return $uri;
+ }
+
+ /**
+ * Preloads a resource.
+ *
+ * @param string $uri A public path
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('crossorigin' => 'use-credentials')")
+ *
+ * @return string The path of the asset
+ */
+ public function preload($uri, array $attributes = array())
+ {
+ return $this->link($uri, 'preload', $attributes);
+ }
+
+ /**
+ * Resolves a resource origin as early as possible.
+ *
+ * @param string $uri A public path
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
+ *
+ * @return string The path of the asset
+ */
+ public function dnsPrefetch($uri, array $attributes = array())
+ {
+ return $this->link($uri, 'dns-prefetch', $attributes);
+ }
+
+ /**
+ * Initiates a early connection to a resource (DNS resolution, TCP handshake, TLS negotiation).
+ *
+ * @param string $uri A public path
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
+ *
+ * @return string The path of the asset
+ */
+ public function preconnect($uri, array $attributes = array())
+ {
+ return $this->link($uri, 'preconnect', $attributes);
+ }
+
+ /**
+ * Indicates to the client that it should prefetch this resource.
+ *
+ * @param string $uri A public path
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
+ *
+ * @return string The path of the asset
+ */
+ public function prefetch($uri, array $attributes = array())
+ {
+ return $this->link($uri, 'prefetch', $attributes);
+ }
+
+ /**
+ * Indicates to the client that it should prerender this resource .
+ *
+ * @param string $uri A public path
+ * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)")
+ *
+ * @return string The path of the asset
+ */
+ public function prerender($uri, array $attributes = array())
+ {
+ return $this->link($uri, 'prerender', $attributes);
+ }
+}
diff --git a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php
index c2c5a55af954f..0e63283ab1905 100644
--- a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php
@@ -32,17 +32,70 @@ public function getFunctions()
return array(
new \Twig_SimpleFunction('workflow_can', array($this, 'canTransition')),
new \Twig_SimpleFunction('workflow_transitions', array($this, 'getEnabledTransitions')),
+ new \Twig_SimpleFunction('workflow_has_marked_place', array($this, 'hasMarkedPlace')),
+ new \Twig_SimpleFunction('workflow_marked_places', array($this, 'getMarkedPlaces')),
);
}
- public function canTransition($object, $transition, $name = null)
+ /**
+ * Returns true if the transition is enabled.
+ *
+ * @param object $subject A subject
+ * @param string $transitionName A transition
+ * @param string $name A workflow name
+ *
+ * @return bool true if the transition is enabled
+ */
+ public function canTransition($subject, $transitionName, $name = null)
{
- return $this->workflowRegistry->get($object, $name)->can($object, $transition);
+ return $this->workflowRegistry->get($subject, $name)->can($subject, $transitionName);
}
- public function getEnabledTransitions($object, $name = null)
+ /**
+ * Returns all enabled transitions.
+ *
+ * @param object $subject A subject
+ * @param string $name A workflow name
+ *
+ * @return Transition[] All enabled transitions
+ */
+ public function getEnabledTransitions($subject, $name = null)
{
- return $this->workflowRegistry->get($object, $name)->getEnabledTransitions($object);
+ return $this->workflowRegistry->get($subject, $name)->getEnabledTransitions($subject);
+ }
+
+ /**
+ * Returns true if the place is marked.
+ *
+ * @param object $subject A subject
+ * @param string $placeName A place name
+ * @param string $name A workflow name
+ *
+ * @return bool true if the transition is enabled
+ */
+ public function hasMarkedPlace($subject, $placeName, $name = null)
+ {
+ return $this->workflowRegistry->get($subject, $name)->getMarking($subject)->has($placeName);
+ }
+
+ /**
+ * Returns marked places.
+ *
+ * @param object $subject A subject
+ * @param string $placesNameOnly If true, returns only places name. If false returns the raw representation
+ * @param string $name A workflow name
+ *
+ * @return string[]|int[]
+ */
+ public function getMarkedPlaces($subject, $placesNameOnly = true, $name = null)
+ {
+ $places = $this->workflowRegistry->get($subject, $name)->getMarking($subject)->getPlaces();
+
+ if ($placesNameOnly) {
+ return array_keys($places);
+ }
+
+ return $places;
}
public function getName()
diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php
index fe99929df0b3d..406726ccdcba0 100644
--- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php
+++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php
@@ -41,9 +41,15 @@ public function __construct(array $defaultThemes = array(), \Twig_Environment $e
/**
* {@inheritdoc}
+ *
+ * @deprecated since version 3.3, to be removed in 4.0
*/
public function setEnvironment(\Twig_Environment $environment)
{
+ if ($this->environment) {
+ @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Pass the Twig Environment as second argument of the constructor instead.', __METHOD__), E_USER_DEPRECATED);
+ }
+
$this->environment = $environment;
}
diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php
index c5968a1fa7683..2fd0cbda79a99 100644
--- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php
+++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php
@@ -16,7 +16,7 @@
/**
* @author Bernhard Schussek
*
- * @deprecated Deprecated since version 3.2, to be removed in 4.0.
+ * @deprecated since version 3.2, to be removed in 4.0.
*/
interface TwigRendererEngineInterface extends FormRendererEngineInterface
{
diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php
index 2b2172b8cce5a..85133248f3850 100644
--- a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php
+++ b/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php
@@ -16,7 +16,7 @@
/**
* @author Bernhard Schussek
*
- * @deprecated Deprecated since version 3.2, to be removed in 4.0.
+ * @deprecated since version 3.2, to be removed in 4.0.
*/
interface TwigRendererInterface extends FormRendererInterface
{
diff --git a/src/Symfony/Bridge/Twig/LICENSE b/src/Symfony/Bridge/Twig/LICENSE
index 12a74531e40a4..17d16a13367dd 100644
--- a/src/Symfony/Bridge/Twig/LICENSE
+++ b/src/Symfony/Bridge/Twig/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2016 Fabien Potencier
+Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
index f9333bf683d1a..1284cf52a20b7 100644
--- a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
+++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
@@ -42,7 +42,7 @@ public function __construct(Scope $parent = null)
/**
* Opens a new child scope.
*
- * @return Scope
+ * @return self
*/
public function enter()
{
@@ -52,7 +52,7 @@ public function enter()
/**
* Closes current scope and returns parent one.
*
- * @return Scope|null
+ * @return self|null
*/
public function leave()
{
@@ -67,7 +67,7 @@ public function leave()
* @param string $key
* @param mixed $value
*
- * @return Scope Current scope
+ * @return $this
*
* @throws \LogicException
*/
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
index 5fb3a18f1d532..f2fe8bf3d2588 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
@@ -94,13 +94,32 @@
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
{{- form_errors(form) -}}
- {%- if with_years %}{{ form_widget(form.years) }}{% endif -%}
- {%- if with_months %}{{ form_widget(form.months) }}{% endif -%}
- {%- if with_weeks %}{{ form_widget(form.weeks) }}{% endif -%}
- {%- if with_days %}{{ form_widget(form.days) }}{% endif -%}
- {%- if with_hours %}{{ form_widget(form.hours) }}{% endif -%}
- {%- if with_minutes %}{{ form_widget(form.minutes) }}{% endif -%}
- {%- if with_seconds %}{{ form_widget(form.seconds) }}{% endif -%}
+
+
+
+
+ {%- if with_years %}{{ form_label(form.years) }} {% endif -%}
+ {%- if with_months %}{{ form_label(form.months) }} {% endif -%}
+ {%- if with_weeks %}{{ form_label(form.weeks) }} {% endif -%}
+ {%- if with_days %}{{ form_label(form.days) }} {% endif -%}
+ {%- if with_hours %}{{ form_label(form.hours) }} {% endif -%}
+ {%- if with_minutes %}{{ form_label(form.minutes) }} {% endif -%}
+ {%- if with_seconds %}{{ form_label(form.seconds) }} {% endif -%}
+
+
+
+
+ {%- if with_years %}{{ form_widget(form.years) }} {% endif -%}
+ {%- if with_months %}{{ form_widget(form.months) }} {% endif -%}
+ {%- if with_weeks %}{{ form_widget(form.weeks) }} {% endif -%}
+ {%- if with_days %}{{ form_widget(form.days) }} {% endif -%}
+ {%- if with_hours %}{{ form_widget(form.hours) }} {% endif -%}
+ {%- if with_minutes %}{{ form_widget(form.minutes) }} {% endif -%}
+ {%- if with_seconds %}{{ form_widget(form.seconds) }} {% endif -%}
+
+
+
+
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
{%- endif -%}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
index e1d09153dfe60..82d52706d9a1a 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -79,7 +79,7 @@
{{- block('choice_widget_options') -}}
{%- else -%}
- {{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}
+ {{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options -%}
@@ -136,13 +136,30 @@
{%- else -%}
{{- form_errors(form) -}}
- {%- if with_years %}{{ form_widget(form.years) }}{% endif -%}
- {%- if with_months %}{{ form_widget(form.months) }}{% endif -%}
- {%- if with_weeks %}{{ form_widget(form.weeks) }}{% endif -%}
- {%- if with_days %}{{ form_widget(form.days) }}{% endif -%}
- {%- if with_hours %}{{ form_widget(form.hours) }}{% endif -%}
- {%- if with_minutes %}{{ form_widget(form.minutes) }}{% endif -%}
- {%- if with_seconds %}{{ form_widget(form.seconds) }}{% endif -%}
+
+
+
+ {%- if with_years %}{{ form_label(form.years) }} {% endif -%}
+ {%- if with_months %}{{ form_label(form.months) }} {% endif -%}
+ {%- if with_weeks %}{{ form_label(form.weeks) }} {% endif -%}
+ {%- if with_days %}{{ form_label(form.days) }} {% endif -%}
+ {%- if with_hours %}{{ form_label(form.hours) }} {% endif -%}
+ {%- if with_minutes %}{{ form_label(form.minutes) }} {% endif -%}
+ {%- if with_seconds %}{{ form_label(form.seconds) }} {% endif -%}
+
+
+
+
+ {%- if with_years %}{{ form_widget(form.years) }} {% endif -%}
+ {%- if with_months %}{{ form_widget(form.months) }} {% endif -%}
+ {%- if with_weeks %}{{ form_widget(form.weeks) }} {% endif -%}
+ {%- if with_days %}{{ form_widget(form.days) }} {% endif -%}
+ {%- if with_hours %}{{ form_widget(form.hours) }} {% endif -%}
+ {%- if with_minutes %}{{ form_widget(form.minutes) }} {% endif -%}
+ {%- if with_seconds %}{{ form_widget(form.seconds) }} {% endif -%}
+
+
+
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
{%- endif -%}
@@ -242,7 +259,7 @@
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
- {{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
+ {{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
{%- endif -%}
{%- endblock form_label -%}
@@ -334,44 +351,17 @@
id="{{ id }}" name="{{ full_name }}"
{%- if disabled %} disabled="disabled"{% endif -%}
{%- if required %} required="required"{% endif -%}
- {%- for attrname, attrvalue in attr -%}
- {{- " " -}}
- {%- if attrname in ['placeholder', 'title'] -%}
- {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}"
- {%- elseif attrvalue is same as(true) -%}
- {{- attrname }}="{{ attrname }}"
- {%- elseif attrvalue is not same as(false) -%}
- {{- attrname }}="{{ attrvalue }}"
- {%- endif -%}
- {%- endfor -%}
+ {{ block('attributes') }}
{%- endblock widget_attributes -%}
{%- block widget_container_attributes -%}
{%- if id is not empty %}id="{{ id }}"{% endif -%}
- {%- for attrname, attrvalue in attr -%}
- {{- " " -}}
- {%- if attrname in ['placeholder', 'title'] -%}
- {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}"
- {%- elseif attrvalue is same as(true) -%}
- {{- attrname }}="{{ attrname }}"
- {%- elseif attrvalue is not same as(false) -%}
- {{- attrname }}="{{ attrvalue }}"
- {%- endif -%}
- {%- endfor -%}
+ {{ block('attributes') }}
{%- endblock widget_container_attributes -%}
{%- block button_attributes -%}
id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%}
- {%- for attrname, attrvalue in attr -%}
- {{- " " -}}
- {%- if attrname in ['placeholder', 'title'] -%}
- {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}"
- {%- elseif attrvalue is same as(true) -%}
- {{- attrname }}="{{ attrname }}"
- {%- elseif attrvalue is not same as(false) -%}
- {{- attrname }}="{{ attrvalue }}"
- {%- endif -%}
- {%- endfor -%}
+ {{ block('attributes') }}
{%- endblock button_attributes -%}
{% block attributes -%}
diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php
index c54ad28ea875a..2a97c269031c8 100644
--- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php
@@ -2,11 +2,13 @@
namespace Symfony\Bridge\Twig\Tests;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\AppVariable;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Session;
-class AppVariableTest extends \PHPUnit_Framework_TestCase
+class AppVariableTest extends TestCase
{
/**
* @var AppVariable
@@ -45,7 +47,7 @@ public function testEnvironment()
public function testGetSession()
{
- $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
+ $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
$request->method('getSession')->willReturn($session = new Session());
$this->setRequestStack($request);
@@ -69,10 +71,10 @@ public function testGetRequest()
public function testGetToken()
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->appVariable->setTokenStorage($tokenStorage);
- $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$tokenStorage->method('getToken')->willReturn($token);
$this->assertEquals($token, $this->appVariable->getToken());
@@ -80,7 +82,7 @@ public function testGetToken()
public function testGetUser()
{
- $this->setTokenStorage($user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
+ $this->setTokenStorage($user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock());
$this->assertEquals($user, $this->appVariable->getUser());
}
@@ -94,7 +96,7 @@ public function testGetUserWithUsernameAsTokenUser()
public function testGetTokenWithNoToken()
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->appVariable->setTokenStorage($tokenStorage);
$this->assertNull($this->appVariable->getToken());
@@ -102,7 +104,7 @@ public function testGetTokenWithNoToken()
public function testGetUserWithNoToken()
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->appVariable->setTokenStorage($tokenStorage);
$this->assertNull($this->appVariable->getUser());
@@ -156,9 +158,79 @@ public function testGetSessionWithRequestStackNotSet()
$this->appVariable->getSession();
}
+ public function testGetFlashesWithNoRequest()
+ {
+ $this->setRequestStack(null);
+
+ $this->assertEquals(array(), $this->appVariable->getFlashes());
+ }
+
+ public function testGetFlashesWithNoSessionStarted()
+ {
+ $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
+ $request->method('getSession')->willReturn(new Session());
+
+ $this->setRequestStack($request);
+
+ $this->assertEquals(array(), $this->appVariable->getFlashes());
+ }
+
+ public function testGetFlashes()
+ {
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals($flashMessages, $this->appVariable->getFlashes(null));
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals($flashMessages, $this->appVariable->getFlashes(''));
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals($flashMessages, $this->appVariable->getFlashes(array()));
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals(array(), $this->appVariable->getFlashes('this-does-not-exist'));
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals(
+ array('this-does-not-exist' => array()),
+ $this->appVariable->getFlashes(array('this-does-not-exist'))
+ );
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals($flashMessages['notice'], $this->appVariable->getFlashes('notice'));
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals(
+ array('notice' => $flashMessages['notice']),
+ $this->appVariable->getFlashes(array('notice'))
+ );
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals(
+ array('notice' => $flashMessages['notice'], 'this-does-not-exist' => array()),
+ $this->appVariable->getFlashes(array('notice', 'this-does-not-exist'))
+ );
+
+ $flashMessages = $this->setFlashMessages();
+ $this->assertEquals(
+ array('notice' => $flashMessages['notice'], 'error' => $flashMessages['error']),
+ $this->appVariable->getFlashes(array('notice', 'error'))
+ );
+
+ $this->assertEquals(
+ array('warning' => $flashMessages['warning']),
+ $this->appVariable->getFlashes(array('warning')),
+ 'After getting some flash types (e.g. "notice" and "error"), the rest of flash messages must remain (e.g. "warning").'
+ );
+
+ $this->assertEquals(
+ array('this-does-not-exist' => array()),
+ $this->appVariable->getFlashes(array('this-does-not-exist'))
+ );
+ }
+
protected function setRequestStack($request)
{
- $requestStackMock = $this->getMock('Symfony\Component\HttpFoundation\RequestStack');
+ $requestStackMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock();
$requestStackMock->method('getCurrentRequest')->willReturn($request);
$this->appVariable->setRequestStack($requestStackMock);
@@ -166,12 +238,33 @@ protected function setRequestStack($request)
protected function setTokenStorage($user)
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->appVariable->setTokenStorage($tokenStorage);
- $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$tokenStorage->method('getToken')->willReturn($token);
$token->method('getUser')->willReturn($user);
}
+
+ private function setFlashMessages()
+ {
+ $flashMessages = array(
+ 'notice' => array('Notice #1 message'),
+ 'warning' => array('Warning #1 message'),
+ 'error' => array('Error #1 message', 'Error #2 message'),
+ );
+ $flashBag = new FlashBag();
+ $flashBag->initialize($flashMessages);
+
+ $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock();
+ $session->method('isStarted')->willReturn(true);
+ $session->method('getFlashBag')->willReturn($flashBag);
+
+ $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
+ $request->method('getSession')->willReturn($session);
+ $this->setRequestStack($request);
+
+ return $flashMessages;
+ }
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php
index 68b20dbbc98f0..1b63cdd1b8daf 100644
--- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bridge\Twig\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Command\LintCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
-class LintCommandTest extends \PHPUnit_Framework_TestCase
+class LintCommandTest extends TestCase
{
private $files;
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
index e1883a526d767..336991c6ca9f2 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
@@ -11,13 +11,12 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\CodeExtension;
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
-class CodeExtensionTest extends \PHPUnit_Framework_TestCase
+class CodeExtensionTest extends TestCase
{
- protected $helper;
-
public function testFormatFile()
{
$expected = sprintf('%s at line 25 ', substr(__FILE__, 5), __FILE__);
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php
index 92803be90e662..df95e4b450b45 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\DumpExtension;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\VarDumper;
use Symfony\Component\VarDumper\Cloner\VarCloner;
-class DumpExtensionTest extends \PHPUnit_Framework_TestCase
+class DumpExtensionTest extends TestCase
{
/**
* @dataProvider getDumpTags
@@ -33,7 +34,7 @@ public function testDumpTag($template, $debug, $expectedOutput, $expectedDumped)
$dumped = null;
$exception = null;
- $prevDumper = VarDumper::setHandler(function ($var) use (&$dumped) {$dumped = $var;});
+ $prevDumper = VarDumper::setHandler(function ($var) use (&$dumped) { $dumped = $var; });
try {
$this->assertEquals($expectedOutput, $twig->render('template'));
@@ -64,7 +65,7 @@ public function getDumpTags()
public function testDump($context, $args, $expectedOutput, $debug = true)
{
$extension = new DumpExtension(new VarCloner());
- $twig = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array(
+ $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array(
'debug' => $debug,
'cache' => false,
'optimizations' => 0,
@@ -120,7 +121,7 @@ public function testCustomDumper()
''
);
$extension = new DumpExtension(new VarCloner(), $dumper);
- $twig = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array(
+ $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array(
'debug' => true,
'cache' => false,
'optimizations' => 0,
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php
index 6d457e395b07e..d689bad20b118 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php
@@ -11,12 +11,11 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\ExpressionExtension;
-class ExpressionExtensionTest extends \PHPUnit_Framework_TestCase
+class ExpressionExtensionTest extends TestCase
{
- protected $helper;
-
public function testExpressionCreation()
{
$template = "{{ expression('1 == 1') }}";
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
index 7ebaa4c2bad51..614b59f5823ec 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
@@ -47,7 +47,7 @@ protected function setUp()
'bootstrap_3_horizontal_layout.html.twig',
'custom_widgets.html.twig',
), $environment);
- $this->renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'));
+ $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock());
$this->registerTwigRuntimeLoader($environment, $this->renderer);
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
index f7919a44f964c..aceda8153d434 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
@@ -43,7 +43,7 @@ protected function setUp()
'bootstrap_3_layout.html.twig',
'custom_widgets.html.twig',
), $environment);
- $this->renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'));
+ $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock());
$this->registerTwigRuntimeLoader($environment, $this->renderer);
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
index f9eb355db31b8..99672997441be 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
@@ -47,7 +47,7 @@ protected function setUp()
'form_div_layout.html.twig',
'custom_widgets.html.twig',
), $environment);
- $this->renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'));
+ $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock());
$this->registerTwigRuntimeLoader($environment, $this->renderer);
}
@@ -89,7 +89,10 @@ public function testThemeBlockInheritanceUsingDynamicExtend()
;
$this->renderer->setTheme($view, array('page_dynamic_extends.html.twig'));
- $this->renderer->searchAndRenderBlock($view, 'row');
+ $this->assertMatchesXpath(
+ $this->renderer->searchAndRenderBlock($view, 'row'),
+ '/div/label[text()="child"]'
+ );
}
public function isSelectedChoiceProvider()
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
index a2726af4390c4..8d4396a54c4dd 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
@@ -44,7 +44,7 @@ protected function setUp()
'form_table_layout.html.twig',
'custom_widgets.html.twig',
), $environment);
- $this->renderer = new TwigRenderer($rendererEngine, $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'));
+ $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock());
$this->registerTwigRuntimeLoader($environment, $this->renderer);
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
index 339d43d7c6bd1..8f0c66ad78bb4 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\HttpFoundationExtension;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContext;
-class HttpFoundationExtensionTest extends \PHPUnit_Framework_TestCase
+class HttpFoundationExtensionTest extends TestCase
{
/**
* @dataProvider getGenerateAbsoluteUrlData()
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
index a583f661d3514..8909b3e4e43b4 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
use Symfony\Bridge\Twig\Extension\HttpKernelRuntime;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
-class HttpKernelExtensionTest extends \PHPUnit_Framework_TestCase
+class HttpKernelExtensionTest extends TestCase
{
/**
* @expectedException \Twig_Error_Runtime
@@ -46,13 +47,19 @@ public function testUnknownFragmentRenderer()
;
$renderer = new FragmentHandler($context);
- $this->setExpectedException('InvalidArgumentException', 'The "inline" renderer does not exist.');
+ if (method_exists($this, 'expectException')) {
+ $this->expectException('InvalidArgumentException');
+ $this->expectExceptionMessage('The "inline" renderer does not exist.');
+ } else {
+ $this->setExpectedException('InvalidArgumentException', 'The "inline" renderer does not exist.');
+ }
+
$renderer->render('/foo');
}
protected function getFragmentHandler($return)
{
- $strategy = $this->getMock('Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface');
+ $strategy = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface')->getMock();
$strategy->expects($this->once())->method('getName')->will($this->returnValue('inline'));
$strategy->expects($this->once())->method('render')->will($return);
@@ -63,9 +70,7 @@ protected function getFragmentHandler($return)
$context->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/')));
- $renderer = new FragmentHandler($context, array($strategy), false);
-
- return $renderer;
+ return new FragmentHandler($context, array($strategy), false);
}
protected function renderTemplate(FragmentHandler $renderer, $template = '{{ render("foo") }}')
@@ -74,7 +79,7 @@ protected function renderTemplate(FragmentHandler $renderer, $template = '{{ ren
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
$twig->addExtension(new HttpKernelExtension());
- $loader = $this->getMock('Twig_RuntimeLoaderInterface');
+ $loader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock();
$loader->expects($this->any())->method('load')->will($this->returnValueMap(array(
array('Symfony\Bridge\Twig\Extension\HttpKernelRuntime', new HttpKernelRuntime($renderer)),
)));
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php
index 9733cd7b8ace6..5fa4e9cd36b1c 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php
@@ -11,17 +11,18 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
-class RoutingExtensionTest extends \PHPUnit_Framework_TestCase
+class RoutingExtensionTest extends TestCase
{
/**
* @dataProvider getEscapingTemplates
*/
public function testEscaping($template, $mustBeEscaped)
{
- $twig = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0));
- $twig->addExtension(new RoutingExtension($this->getMock('Symfony\Component\Routing\Generator\UrlGeneratorInterface')));
+ $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0));
+ $twig->addExtension(new RoutingExtension($this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock()));
$nodes = $twig->parse($twig->tokenize(new \Twig_Source($template, '')));
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php
index 12ae07f8d48b0..a6c397ffd4d90 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php
@@ -17,7 +17,7 @@ trait RuntimeLoaderProvider
{
protected function registerTwigRuntimeLoader(\Twig_Environment $environment, TwigRenderer $renderer)
{
- $loader = $this->getMock('Twig_RuntimeLoaderInterface');
+ $loader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock();
$loader->expects($this->any())->method('load')->will($this->returnValueMap(array(
array('Symfony\Bridge\Twig\Form\TwigRenderer', $renderer),
)));
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php
index daca220e493e0..c50252eaafcca 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\StopwatchExtension;
-class StopwatchExtensionTest extends \PHPUnit_Framework_TestCase
+class StopwatchExtensionTest extends TestCase
{
/**
* @expectedException \Twig_Error_Syntax
@@ -53,7 +54,7 @@ public function getTimingTemplates()
protected function getStopwatch($events = array())
{
$events = is_array($events) ? $events : array($events);
- $stopwatch = $this->getMock('Symfony\Component\Stopwatch\Stopwatch');
+ $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')->getMock();
$i = -1;
foreach ($events as $eventName) {
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
index e96bd4f9a3bef..446697d3dd8b2 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bridge\Twig\Tests\Extension;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;
-class TranslationExtensionTest extends \PHPUnit_Framework_TestCase
+class TranslationExtensionTest extends TestCase
{
public function testEscaping()
{
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/WebLinkExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/WebLinkExtensionTest.php
new file mode 100644
index 0000000000000..3424b58875fbc
--- /dev/null
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/WebLinkExtensionTest.php
@@ -0,0 +1,92 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\Twig\Tests\Extension;
+
+use Fig\Link\Link;
+use PHPUnit\Framework\TestCase;
+use Symfony\Bridge\Twig\Extension\WebLinkExtension;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * @author Kévin Dunglas
+ */
+class WebLinkExtensionTest extends TestCase
+{
+ /**
+ * @var Request
+ */
+ private $request;
+
+ /**
+ * @var WebLinkExtension
+ */
+ private $extension;
+
+ protected function setUp()
+ {
+ $this->request = new Request();
+
+ $requestStack = new RequestStack();
+ $requestStack->push($this->request);
+
+ $this->extension = new WebLinkExtension($requestStack);
+ }
+
+ public function testLink()
+ {
+ $this->assertEquals('/foo.css', $this->extension->link('/foo.css', 'preload', array('as' => 'style', 'nopush' => true)));
+
+ $link = (new Link('preload', '/foo.css'))->withAttribute('as', 'style')->withAttribute('nopush', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+
+ public function testPreload()
+ {
+ $this->assertEquals('/foo.css', $this->extension->preload('/foo.css', array('as' => 'style', 'crossorigin' => true)));
+
+ $link = (new Link('preload', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+
+ public function testDnsPrefetch()
+ {
+ $this->assertEquals('/foo.css', $this->extension->dnsPrefetch('/foo.css', array('as' => 'style', 'crossorigin' => true)));
+
+ $link = (new Link('dns-prefetch', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+
+ public function testPreconnect()
+ {
+ $this->assertEquals('/foo.css', $this->extension->preconnect('/foo.css', array('as' => 'style', 'crossorigin' => true)));
+
+ $link = (new Link('preconnect', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+
+ public function testPrefetch()
+ {
+ $this->assertEquals('/foo.css', $this->extension->prefetch('/foo.css', array('as' => 'style', 'crossorigin' => true)));
+
+ $link = (new Link('prefetch', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+
+ public function testPrerender()
+ {
+ $this->assertEquals('/foo.css', $this->extension->prerender('/foo.css', array('as' => 'style', 'crossorigin' => true)));
+
+ $link = (new Link('prerender', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true);
+ $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks()));
+ }
+}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php
new file mode 100644
index 0000000000000..e134434c9b4e7
--- /dev/null
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php
@@ -0,0 +1,88 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\Twig\Tests\Extension;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Bridge\Twig\Extension\WorkflowExtension;
+use Symfony\Component\Workflow\Definition;
+use Symfony\Component\Workflow\Marking;
+use Symfony\Component\Workflow\Registry;
+use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
+use Symfony\Component\Workflow\Transition;
+use Symfony\Component\Workflow\Workflow;
+
+class WorkflowExtensionTest extends TestCase
+{
+ private $extension;
+
+ protected function setUp()
+ {
+ if (!class_exists(Workflow::class)) {
+ $this->markTestSkipped('The Workflow component is needed to run tests for this extension.');
+ }
+
+ $places = array('ordered', 'waiting_for_payment', 'processed');
+ $transitions = array(
+ new Transition('t1', 'ordered', 'waiting_for_payment'),
+ new Transition('t2', 'waiting_for_payment', 'processed'),
+ );
+ $definition = new Definition($places, $transitions);
+ $workflow = new Workflow($definition);
+
+ $registry = new Registry();
+ $registry->add($workflow, new ClassInstanceSupportStrategy(\stdClass::class));
+
+ $this->extension = new WorkflowExtension($registry);
+ }
+
+ public function testCanTransition()
+ {
+ $subject = new \stdClass();
+ $subject->marking = array();
+
+ $this->assertTrue($this->extension->canTransition($subject, 't1'));
+ $this->assertFalse($this->extension->canTransition($subject, 't2'));
+ }
+
+ public function testGetEnabledTransitions()
+ {
+ $subject = new \stdClass();
+ $subject->marking = array();
+
+ $transitions = $this->extension->getEnabledTransitions($subject);
+
+ $this->assertCount(1, $transitions);
+ $this->assertInstanceOf(Transition::class, $transitions[0]);
+ $this->assertSame('t1', $transitions[0]->getName());
+ }
+
+ public function testHasMarkedPlace()
+ {
+ $subject = new \stdClass();
+ $subject->marking = array();
+ $subject->marking = array('ordered' => 1, 'waiting_for_payment' => 1);
+
+ $this->assertTrue($this->extension->hasMarkedPlace($subject, 'ordered'));
+ $this->assertTrue($this->extension->hasMarkedPlace($subject, 'waiting_for_payment'));
+ $this->assertFalse($this->extension->hasMarkedPlace($subject, 'processed'));
+ }
+
+ public function testGetMarkedPlaces()
+ {
+ $subject = new \stdClass();
+ $subject->marking = array();
+ $subject->marking = array('ordered' => 1, 'waiting_for_payment' => 1);
+
+ $this->assertSame(array('ordered', 'waiting_for_payment'), $this->extension->getMarkedPlaces($subject));
+ $this->assertSame($subject->marking, $this->extension->getMarkedPlaces($subject, false));
+ }
+}
diff --git a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php
index 5d669cde7ac94..5e589c2db11db 100644
--- a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php
@@ -11,15 +11,16 @@
namespace Symfony\Bridge\Twig\Tests\Node;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Node\DumpNode;
-class DumpNodeTest extends \PHPUnit_Framework_TestCase
+class DumpNodeTest extends TestCase
{
public function testNoVar()
{
$node = new DumpNode('bar', null, 7);
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$compiler = new \Twig_Compiler($env);
$expected = <<<'EOTXT'
@@ -43,7 +44,7 @@ public function testIndented()
{
$node = new DumpNode('bar', null, 7);
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$compiler = new \Twig_Compiler($env);
$expected = <<<'EOTXT'
@@ -70,7 +71,7 @@ public function testOneVar()
));
$node = new DumpNode('bar', $vars, 7);
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$compiler = new \Twig_Compiler($env);
$expected = <<<'EOTXT'
@@ -98,7 +99,7 @@ public function testMultiVars()
));
$node = new DumpNode('bar', $vars, 7);
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$compiler = new \Twig_Compiler($env);
$expected = <<<'EOTXT'
diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php
index dff1d5f5ae090..9d3576e0b4430 100644
--- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bridge\Twig\Tests\Node;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Node\FormThemeNode;
-class FormThemeTest extends \PHPUnit_Framework_TestCase
+class FormThemeTest extends TestCase
{
public function testConstructor()
{
@@ -41,7 +42,7 @@ public function testCompile()
$node = new FormThemeNode($form, $resources, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php
index 31ab934f37ec8..b292ef63f8555 100644
--- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bridge\Twig\Tests\Node;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode;
-class SearchAndRenderBlockNodeTest extends \PHPUnit_Framework_TestCase
+class SearchAndRenderBlockNodeTest extends TestCase
{
public function testCompileWidget()
{
@@ -23,7 +24,7 @@ public function testCompileWidget()
$node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
@@ -46,7 +47,7 @@ public function testCompileWidgetWithVariables()
$node = new SearchAndRenderBlockNode('form_widget', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
@@ -66,7 +67,7 @@ public function testCompileLabelWithLabel()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
@@ -86,7 +87,7 @@ public function testCompileLabelWithNullLabel()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
// "label" => null must not be included in the output!
// Otherwise the default label is overwritten with null.
@@ -108,7 +109,7 @@ public function testCompileLabelWithEmptyStringLabel()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
// "label" => null must not be included in the output!
// Otherwise the default label is overwritten with null.
@@ -129,7 +130,7 @@ public function testCompileLabelWithDefaultLabel()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
@@ -153,7 +154,7 @@ public function testCompileLabelWithAttributes()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
// "label" => null must not be included in the output!
// Otherwise the default label is overwritten with null.
@@ -182,7 +183,7 @@ public function testCompileLabelWithLabelAndAttributes()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
$this->assertEquals(
sprintf(
@@ -210,7 +211,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNull()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
// "label" => null must not be included in the output!
// Otherwise the default label is overwritten with null.
@@ -247,7 +248,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes()
$node = new SearchAndRenderBlockNode('form_label', $arguments, 0);
- $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMock('Twig_LoaderInterface')));
+ $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
// "label" => null must not be included in the output!
// Otherwise the default label is overwritten with null.
diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php
index 4c00cdab50ade..5862006f3826a 100644
--- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bridge\Twig\Tests\Node;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Node\TransNode;
/**
* @author Asmir Mustafic
*/
-class TransNodeTest extends \PHPUnit_Framework_TestCase
+class TransNodeTest extends TestCase
{
public function testCompileStrict()
{
@@ -24,7 +25,7 @@ public function testCompileStrict()
$vars = new \Twig_Node_Expression_Name('foo', 0);
$node = new TransNode($body, null, null, $vars);
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('strict_variables' => true));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true));
$compiler = new \Twig_Compiler($env);
$this->assertEquals(
@@ -49,7 +50,7 @@ protected function getVariableGetterWithoutStrictCheck($name)
protected function getVariableGetterWithStrictCheck($name)
{
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);
+ 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) {
diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php
index aa9d204e5606f..fad0e1f829763 100644
--- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/ScopeTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\NodeVisitor\Scope;
-class ScopeTest extends \PHPUnit_Framework_TestCase
+class ScopeTest extends TestCase
{
public function testScopeInitiation()
{
diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php
index f9cf08bc28017..da9f43a6c4e0e 100644
--- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
-class TranslationDefaultDomainNodeVisitorTest extends \PHPUnit_Framework_TestCase
+class TranslationDefaultDomainNodeVisitorTest extends TestCase
{
private static $message = 'message';
private static $domain = 'domain';
@@ -22,7 +23,7 @@ class TranslationDefaultDomainNodeVisitorTest extends \PHPUnit_Framework_TestCas
/** @dataProvider getDefaultDomainAssignmentTestData */
public function testDefaultDomainAssignment(\Twig_Node $node)
{
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
$visitor = new TranslationDefaultDomainNodeVisitor();
// visit trans_default_domain tag
@@ -48,7 +49,7 @@ public function testDefaultDomainAssignment(\Twig_Node $node)
/** @dataProvider getDefaultDomainAssignmentTestData */
public function testNewModuleWithoutDefaultDomainTag(\Twig_Node $node)
{
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
$visitor = new TranslationDefaultDomainNodeVisitor();
// visit trans_default_domain tag
diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php
index 16736031e087d..d12fff532aaa1 100644
--- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php
@@ -11,14 +11,15 @@
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
-class TranslationNodeVisitorTest extends \PHPUnit_Framework_TestCase
+class TranslationNodeVisitorTest extends TestCase
{
/** @dataProvider getMessagesExtractionTestData */
public function testMessagesExtraction(\Twig_Node $node, array $expectedMessages)
{
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
$visitor = new TranslationNodeVisitor();
$visitor->enable();
$visitor->enterNode($node, $env);
diff --git a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php
index 6b6a92abf1434..8931be061f9d2 100644
--- a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php
@@ -11,17 +11,18 @@
namespace Symfony\Bridge\Twig\Tests\TokenParser;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
use Symfony\Bridge\Twig\Node\FormThemeNode;
-class FormThemeTokenParserTest extends \PHPUnit_Framework_TestCase
+class FormThemeTokenParserTest extends TestCase
{
/**
* @dataProvider getTestsForFormTheme
*/
public function testCompile($source, $expected)
{
- $env = new \Twig_Environment($this->getMock('Twig_LoaderInterface'), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
+ $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
$env->addTokenParser(new FormThemeTokenParser());
$stream = $env->tokenize(new \Twig_Source($source, ''));
$parser = new \Twig_Parser($env);
diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php
index 5e7c4ce5216d0..0b1fb28b0e10c 100644
--- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php
@@ -11,25 +11,26 @@
namespace Symfony\Bridge\Twig\Tests\Translation;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Translation\TwigExtractor;
use Symfony\Component\Translation\MessageCatalogue;
-class TwigExtractorTest extends \PHPUnit_Framework_TestCase
+class TwigExtractorTest extends TestCase
{
/**
* @dataProvider getExtractData
*/
public function testExtract($template, $messages)
{
- $loader = $this->getMock('Twig_LoaderInterface');
+ $loader = $this->getMockBuilder('Twig_LoaderInterface')->getMock();
$twig = new \Twig_Environment($loader, array(
'strict_variables' => true,
'debug' => true,
'cache' => false,
'autoescape' => false,
));
- $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));
+ $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock()));
$extractor = new TwigExtractor($twig);
$extractor->setPrefix('prefix');
@@ -72,17 +73,28 @@ public function getExtractData()
}
/**
- * @expectedException \Twig_Error
- * @expectedExceptionMessageRegExp /Unclosed "block" in ".*extractor(\/|\\)syntax_error\.twig" at line 1/
+ * @expectedException \Twig_Error
* @dataProvider resourcesWithSyntaxErrorsProvider
*/
public function testExtractSyntaxError($resources)
{
- $twig = new \Twig_Environment($this->getMock('Twig_LoaderInterface'));
- $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));
+ $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
+ $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock()));
$extractor = new TwigExtractor($twig);
- $extractor->extract($resources, new MessageCatalogue('en'));
+
+ try {
+ $extractor->extract($resources, new MessageCatalogue('en'));
+ } catch (\Twig_Error $e) {
+ if (method_exists($e, 'getSourceContext')) {
+ $this->assertSame(dirname(__DIR__).strtr('/Fixtures/extractor/syntax_error.twig', '/', DIRECTORY_SEPARATOR), $e->getFile());
+ $this->assertSame(1, $e->getLine());
+ $this->assertSame('Unclosed "block".', $e->getMessage());
+ } else {
+ $this->expectExceptionMessageRegExp('/Unclosed "block" in ".*extractor(\\/|\\\\)syntax_error\\.twig" at line 1/');
+ }
+ throw $e;
+ }
}
/**
@@ -109,7 +121,7 @@ public function testExtractWithFiles($resource)
'cache' => false,
'autoescape' => false,
));
- $twig->addExtension(new TranslationExtension($this->getMock('Symfony\Component\Translation\TranslatorInterface')));
+ $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock()));
$extractor = new TwigExtractor($twig);
$catalogue = new MessageCatalogue('en');
diff --git a/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php b/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php
index e7047c354d080..e2082df3dd75b 100644
--- a/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bridge\Twig\Tests;
+use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\Templating\TemplateReference;
-class TwigEngineTest extends \PHPUnit_Framework_TestCase
+class TwigEngineTest extends TestCase
{
public function testExistsWithTemplateInstances()
{
@@ -71,7 +72,7 @@ protected function getTwig()
'index' => 'foo',
'error' => '{{ foo }',
)));
- $parser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface');
+ $parser = $this->getMockBuilder('Symfony\Component\Templating\TemplateNameParserInterface')->getMock();
return new TwigEngine($twig, $parser);
}
diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php
index 950c4d0810db0..35995dbd64518 100644
--- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php
+++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php
@@ -61,10 +61,14 @@ public function extract($resource, MessageCatalogue $catalogue)
try {
$this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
} catch (\Twig_Error $e) {
- if ($file instanceof SplFileInfo) {
- $e->setTemplateName($file->getRelativePathname());
- } elseif ($file instanceof \SplFileInfo) {
- $e->setTemplateName($file->getRealPath() ?: $file->getPathname());
+ if ($file instanceof \SplFileInfo) {
+ $path = $file->getRealPath() ?: $file->getPathname();
+ $name = $file instanceof SplFileInfo ? $file->getRelativePathname() : $path;
+ if (method_exists($e, 'setSourceContext')) {
+ $e->setSourceContext(new \Twig_Source('', $name, $path));
+ } else {
+ $e->setTemplateName($name);
+ }
}
throw $e;
diff --git a/src/Symfony/Bridge/Twig/TwigEngine.php b/src/Symfony/Bridge/Twig/TwigEngine.php
index 1ac9d0102e63b..760461b5be578 100644
--- a/src/Symfony/Bridge/Twig/TwigEngine.php
+++ b/src/Symfony/Bridge/Twig/TwigEngine.php
@@ -112,7 +112,7 @@ public function supports($name)
* @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of
* TemplateReferenceInterface or \Twig_Template
*
- * @return \Twig_TemplateInterface A \Twig_TemplateInterface instance
+ * @return \Twig_Template A \Twig_Template instance
*
* @throws \InvalidArgumentException if the template does not exist
*/
diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json
index fd73a7ea3d346..38949fad20792 100644
--- a/src/Symfony/Bridge/Twig/composer.json
+++ b/src/Symfony/Bridge/Twig/composer.json
@@ -20,9 +20,10 @@
"twig/twig": "~1.28|~2.0"
},
"require-dev": {
+ "fig/link-util": "^1.0",
"symfony/asset": "~2.8|~3.0",
"symfony/finder": "~2.8|~3.0",
- "symfony/form": "~3.0.4",
+ "symfony/form": "^3.2.7",
"symfony/http-kernel": "~3.2",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/routing": "~2.8|~3.0",
@@ -34,7 +35,8 @@
"symfony/stopwatch": "~2.8|~3.0",
"symfony/console": "~2.8|~3.0",
"symfony/var-dumper": "~2.8.10|~3.1.4|~3.2",
- "symfony/expression-language": "~2.8|~3.0"
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/web-link": "~3.3"
},
"suggest": {
"symfony/finder": "",
@@ -48,7 +50,8 @@
"symfony/security": "For using the SecurityExtension",
"symfony/stopwatch": "For using the StopwatchExtension",
"symfony/var-dumper": "For using the DumpExtension",
- "symfony/expression-language": "For using the ExpressionExtension"
+ "symfony/expression-language": "For using the ExpressionExtension",
+ "symfony/web-link": "For using the WebLinkExtension"
},
"autoload": {
"psr-4": { "Symfony\\Bridge\\Twig\\": "" },
@@ -59,7 +62,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bridge/Twig/phpunit.xml.dist b/src/Symfony/Bridge/Twig/phpunit.xml.dist
index 10c0be1142712..642b7d19d8b70 100644
--- a/src/Symfony/Bridge/Twig/phpunit.xml.dist
+++ b/src/Symfony/Bridge/Twig/phpunit.xml.dist
@@ -5,6 +5,8 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
diff --git a/src/Symfony/Bundle/DebugBundle/LICENSE b/src/Symfony/Bundle/DebugBundle/LICENSE
index 39fa189d2b5fc..207646a052dcd 100644
--- a/src/Symfony/Bundle/DebugBundle/LICENSE
+++ b/src/Symfony/Bundle/DebugBundle/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014-2016 Fabien Potencier
+Copyright (c) 2014-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml
index aada03eff87cf..ae7d91add15d4 100644
--- a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml
@@ -14,7 +14,7 @@
-
+
%kernel.charset%
null
@@ -38,7 +38,7 @@
0
-
+
diff --git a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php
index 4500fac7215b2..6f49c021260ed 100644
--- a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php
+++ b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/Compiler/DumpDataCollectorPassTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpFoundation\RequestStack;
-class DumpDataCollectorPassTest extends \PHPUnit_Framework_TestCase
+class DumpDataCollectorPassTest extends TestCase
{
public function testProcessWithoutFileLinkFormatParameter()
{
diff --git a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php
index fc4e620e81a4c..9c03e9988224a 100644
--- a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php
+++ b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php
@@ -11,11 +11,12 @@
namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\DebugBundle\DependencyInjection\DebugExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
-class DebugExtensionTest extends \PHPUnit_Framework_TestCase
+class DebugExtensionTest extends TestCase
{
public function testLoadWithoutConfiguration()
{
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index e5fe655296473..d6d7d0b33b16f 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -39,7 +39,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist b/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist
index 90ec0a5dba514..3df3f74a7d9a5 100644
--- a/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist
+++ b/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist
@@ -5,6 +5,8 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index efee66b41cecf..df80163243c1c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -1,6 +1,55 @@
CHANGELOG
=========
+3.3.0
+-----
+
+ * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated.
+ The default value will be `state_machine` in Symfony 4.0.
+ * Deprecated the `CompilerDebugDumpPass` class
+ * [BC BREAK] Removed the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter
+ * Added a new new version strategy option called json_manifest_path
+ that allows you to use the `JsonManifestVersionStrategy`.
+ * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides
+ the same helpers as the `Controller` class, but does not allow accessing the dependency
+ injection container, in order to encourage explicit dependency declarations.
+ * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions
+ * Deprecated `cache:clear` with warmup (always call it with `--no-warmup`)
+ * Changed default configuration for
+ assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to
+ `canBeDisabled()` when Flex is used
+ * The server:* commands and their associated router files were moved to WebServerBundle
+ * Translation related services are not loaded anymore when the `framework.translator` option
+ is disabled.
+ * Added `GlobalVariables::getToken()`
+ * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead.
+ * Added configurable paths for validation files
+ * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead
+ * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead
+ * Deprecated `SessionListener`
+ * Deprecated `TestSessionListener`
+ * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
+ Use `Symfony\Component\Console\DependencyInjection\ConfigCachePass` instead.
+ * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead
+ * Deprecated extending `ConstraintValidatorFactory`
+ * Deprecated `ControllerArgumentValueResolverPass`. Use
+ `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead
+ * Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead
+ * [BC BREAK] The `server:run`, `server:start`, `server:stop` and
+ `server:status` console commands have been moved to a dedicated bundle.
+ Require `symfony/web-server-bundle` in your composer.json and register
+ `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them.
+ * Added `$defaultLocale` as 3rd argument of `Translator::__construct()`
+ making `Translator` works with any PSR-11 container
+ * Added `framework.serializer.mapping` config option allowing to define custom
+ serialization mapping files and directories
+ * Deprecated `AddValidatorInitializersPass`, use
+ `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead
+ * Deprecated `AddConstraintValidatorsPass`, use
+ `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead
+ * Deprecated `ValidateWorkflowsPass`, use
+ `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead
+
3.2.0
-----
@@ -11,7 +60,7 @@ CHANGELOG
* Removed `symfony/asset` from the list of required dependencies in `composer.json`
* The `Resources/public/images/*` files have been removed.
* The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle).
- * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension`
+ * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension`
3.1.0
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php
index 6d044676eb012..a6fb4ed095d2b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
+use Doctrine\Common\Annotations\AnnotationException;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Annotations\Reader;
use Psr\Cache\CacheItemPoolInterface;
@@ -35,8 +36,8 @@ class AnnotationsCacheWarmer implements CacheWarmerInterface
/**
* @param Reader $annotationReader
- * @param string $phpArrayFile The PHP file where annotations are cached.
- * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered annotations are cached.
+ * @param string $phpArrayFile The PHP file where annotations are cached
+ * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered annotations are cached
*/
public function __construct(Reader $annotationReader, $phpArrayFile, CacheItemPoolInterface $fallbackPool)
{
@@ -67,8 +68,26 @@ public function warmUp($cacheDir)
$arrayPool = new ArrayAdapter(0, false);
$reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayPool));
- foreach ($annotatedClasses as $class) {
- $this->readAllComponents($reader, $class);
+ spl_autoload_register(array($adapter, 'throwOnRequiredClass'));
+ try {
+ foreach ($annotatedClasses as $class) {
+ try {
+ $this->readAllComponents($reader, $class);
+ } catch (\ReflectionException $e) {
+ // ignore failing reflection
+ } catch (AnnotationException $e) {
+ /*
+ * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly
+ * configured or could not be found / read / etc.
+ *
+ * In particular cases, an Annotation in your code can be used and defined only for a specific
+ * environment but is always added to the annotations.map file by some Symfony default behaviors,
+ * and you always end up with a not found Annotation.
+ */
+ }
+ }
+ } finally {
+ spl_autoload_unregister(array($adapter, 'throwOnRequiredClass'));
}
$values = $arrayPool->getValues();
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php
index b235c65136555..1240f14c5b749 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php
@@ -18,6 +18,8 @@
* Generates the Class Cache (classes.php) file.
*
* @author Tugdual Saunier
+ *
+ * @deprecated since version 3.3, to be removed in 4.0.
*/
class ClassCacheCacheWarmer implements CacheWarmerInterface
{
@@ -25,6 +27,10 @@ class ClassCacheCacheWarmer implements CacheWarmerInterface
public function __construct(array $declaredClasses = null)
{
+ if (PHP_VERSION_ID >= 70000) {
+ @trigger_error('The '.__CLASS__.' class is deprecated since version 3.3 and will be removed in 4.0.', E_USER_DEPRECATED);
+ }
+
$this->declaredClasses = $declaredClasses;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php
index 23e6142be4993..c017f51268b3d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
+use Doctrine\Common\Annotations\AnnotationException;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
@@ -36,9 +37,9 @@ class SerializerCacheWarmer implements CacheWarmerInterface
private $fallbackPool;
/**
- * @param LoaderInterface[] $loaders The serializer metadata loaders.
- * @param string $phpArrayFile The PHP file where metadata are cached.
- * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached.
+ * @param LoaderInterface[] $loaders The serializer metadata loaders
+ * @param string $phpArrayFile The PHP file where metadata are cached
+ * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached
*/
public function __construct(array $loaders, $phpArrayFile, CacheItemPoolInterface $fallbackPool)
{
@@ -64,10 +65,21 @@ public function warmUp($cacheDir)
$metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayPool);
- foreach ($this->extractSupportedLoaders($this->loaders) as $loader) {
- foreach ($loader->getMappedClasses() as $mappedClass) {
- $metadataFactory->getMetadataFor($mappedClass);
+ spl_autoload_register(array($adapter, 'throwOnRequiredClass'));
+ try {
+ foreach ($this->extractSupportedLoaders($this->loaders) as $loader) {
+ foreach ($loader->getMappedClasses() as $mappedClass) {
+ try {
+ $metadataFactory->getMetadataFor($mappedClass);
+ } catch (\ReflectionException $e) {
+ // ignore failing reflection
+ } catch (AnnotationException $e) {
+ // ignore failing annotations
+ }
+ }
}
+ } finally {
+ spl_autoload_unregister(array($adapter, 'throwOnRequiredClass'));
}
$values = $arrayPool->getValues();
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php
index 1e229849824ac..afda1191777b8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php
@@ -14,6 +14,7 @@
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Templating\TemplateNameParserInterface;
+use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php
index e7db48a010fa9..4cb9f41b29556 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php
@@ -35,7 +35,6 @@ public function __construct(TemplateFinderInterface $finder, TemplateLocator $lo
{
$this->finder = $finder;
$this->locator = $locator;
- $this->filesystem = new Filesystem();
}
/**
@@ -45,10 +44,11 @@ public function __construct(TemplateFinderInterface $finder, TemplateLocator $lo
*/
public function warmUp($cacheDir)
{
+ $filesystem = new Filesystem();
$templates = array();
foreach ($this->finder->findAllTemplates() as $template) {
- $templates[$template->getLogicalName()] = rtrim($this->filesystem->makePathRelative($this->locator->locate($template), $cacheDir), '/');
+ $templates[$template->getLogicalName()] = rtrim($filesystem->makePathRelative($this->locator->locate($template), $cacheDir), '/');
}
$templates = str_replace("' => '", "' => __DIR__.'/", var_export($templates, true));
diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php
index ce5104dc41cc5..81291d772fbf0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php
+++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
+use Doctrine\Common\Annotations\AnnotationException;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
@@ -38,8 +39,8 @@ class ValidatorCacheWarmer implements CacheWarmerInterface
/**
* @param ValidatorBuilderInterface $validatorBuilder
- * @param string $phpArrayFile The PHP file where metadata are cached.
- * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached.
+ * @param string $phpArrayFile The PHP file where metadata are cached
+ * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached
*/
public function __construct(ValidatorBuilderInterface $validatorBuilder, $phpArrayFile, CacheItemPoolInterface $fallbackPool)
{
@@ -66,16 +67,27 @@ public function warmUp($cacheDir)
$loaders = $this->validatorBuilder->getLoaders();
$metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), new Psr6Cache($arrayPool));
- foreach ($this->extractSupportedLoaders($loaders) as $loader) {
- foreach ($loader->getMappedClasses() as $mappedClass) {
- if ($metadataFactory->hasMetadataFor($mappedClass)) {
- $metadataFactory->getMetadataFor($mappedClass);
+ spl_autoload_register(array($adapter, 'throwOnRequiredClass'));
+ try {
+ foreach ($this->extractSupportedLoaders($loaders) as $loader) {
+ foreach ($loader->getMappedClasses() as $mappedClass) {
+ try {
+ if ($metadataFactory->hasMetadataFor($mappedClass)) {
+ $metadataFactory->getMetadataFor($mappedClass);
+ }
+ } catch (\ReflectionException $e) {
+ // ignore failing reflection
+ } catch (AnnotationException $e) {
+ // ignore failing annotations
+ }
}
}
+ } finally {
+ spl_autoload_unregister(array($adapter, 'throwOnRequiredClass'));
}
$values = $arrayPool->getValues();
- $adapter->warmUp($values);
+ $adapter->warmUp(array_filter($values));
foreach ($values as $k => $v) {
$item = $this->fallbackPool->getItem($k);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Client.php b/src/Symfony/Bundle/FrameworkBundle/Client.php
index 04fbd3ab0fab2..2238ae859498d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Client.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Client.php
@@ -163,34 +163,36 @@ protected function getScript($request)
{
$kernel = str_replace("'", "\\'", serialize($this->kernel));
$request = str_replace("'", "\\'", serialize($request));
+ $errorReporting = error_reporting();
- $r = new \ReflectionObject($this->kernel);
+ $requires = '';
+ foreach (get_declared_classes() as $class) {
+ if (0 === strpos($class, 'ComposerAutoloaderInit')) {
+ $r = new \ReflectionClass($class);
+ $file = dirname(dirname($r->getFileName())).'/autoload.php';
+ if (file_exists($file)) {
+ $requires .= "require_once '".str_replace("'", "\\'", $file)."';\n";
+ }
+ }
+ }
- $autoloader = dirname($r->getFileName()).'/autoload.php';
- if (is_file($autoloader)) {
- $autoloader = str_replace("'", "\\'", $autoloader);
- } else {
- $autoloader = '';
+ if (!$requires) {
+ throw new \RuntimeException('Composer autoloader not found.');
}
- $path = str_replace("'", "\\'", $r->getFileName());
+ $requires .= "require_once '".str_replace("'", "\\'", (new \ReflectionObject($this->kernel))->getFileName())."';\n";
$profilerCode = '';
if ($this->profiler) {
$profilerCode = '$kernel->getContainer()->get(\'profiler\')->enable();';
}
- $errorReporting = error_reporting();
-
$code = <<boot();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php
new file mode 100644
index 0000000000000..cb6f43a43c106
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php
@@ -0,0 +1,106 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Command;
+
+use Symfony\Component\Console\Helper\Helper;
+use Symfony\Component\Console\Helper\TableSeparator;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\HttpKernel\KernelInterface;
+
+/**
+ * A console command to display information about the current installation.
+ *
+ * @author Roland Franssen
+ */
+class AboutCommand extends ContainerAwareCommand
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setName('about')
+ ->setDescription('Displays information about the current project')
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ /** @var $kernel KernelInterface */
+ $kernel = $this->getContainer()->get('kernel');
+ $baseDir = realpath($kernel->getRootDir().DIRECTORY_SEPARATOR.'..');
+
+ $io->table(array(), array(
+ array('Symfony>'),
+ new TableSeparator(),
+ array('Version', Kernel::VERSION),
+ array('End of maintenance', Kernel::END_OF_MAINTENANCE.(self::isExpired(Kernel::END_OF_MAINTENANCE) ? ' Expired>' : '')),
+ array('End of life', Kernel::END_OF_LIFE.(self::isExpired(Kernel::END_OF_LIFE) ? ' Expired>' : '')),
+ new TableSeparator(),
+ array('Kernel>'),
+ new TableSeparator(),
+ array('Type', get_class($kernel)),
+ array('Name', $kernel->getName()),
+ array('Environment', $kernel->getEnvironment()),
+ array('Debug', $kernel->isDebug() ? 'true' : 'false'),
+ array('Charset', $kernel->getCharset()),
+ array('Root directory', self::formatPath($kernel->getRootDir(), $baseDir)),
+ array('Cache directory', self::formatPath($kernel->getCacheDir(), $baseDir).' ('.self::formatFileSize($kernel->getCacheDir()).'>)'),
+ array('Log directory', self::formatPath($kernel->getLogDir(), $baseDir).' ('.self::formatFileSize($kernel->getLogDir()).'>)'),
+ new TableSeparator(),
+ array('PHP>'),
+ new TableSeparator(),
+ array('Version', PHP_VERSION),
+ array('Architecture', (PHP_INT_SIZE * 8).' bits'),
+ array('Intl locale', \Locale::getDefault() ?: 'n/a'),
+ array('Timezone', date_default_timezone_get().' ('.(new \DateTime())->format(\DateTime::W3C).'>)'),
+ array('OPcache', extension_loaded('Zend OPcache') && ini_get('opcache.enable') ? 'true' : 'false'),
+ array('APCu', extension_loaded('apcu') && ini_get('apc.enabled') ? 'true' : 'false'),
+ array('Xdebug', extension_loaded('xdebug') ? 'true' : 'false'),
+ ));
+ }
+
+ private static function formatPath($path, $baseDir = null)
+ {
+ return null !== $baseDir ? preg_replace('~^'.preg_quote($baseDir, '~').'~', '.', $path) : $path;
+ }
+
+ private static function formatFileSize($path)
+ {
+ if (is_file($path)) {
+ $size = filesize($path) ?: 0;
+ } else {
+ $size = 0;
+ foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS)) as $file) {
+ $size += $file->getSize();
+ }
+ }
+
+ return Helper::formatMemory($size);
+ }
+
+ private static function isExpired($date)
+ {
+ $date = \DateTime::createFromFormat('m/Y', $date);
+
+ return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59');
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 9f36c8d714d72..feb966d850939 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -82,7 +82,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$targetArg = rtrim($input->getArgument('target'), '/');
if (!is_dir($targetArg)) {
- throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
+ $appRoot = $this->getContainer()->getParameter('kernel.root_dir').'/..';
+
+ $targetArg = $appRoot.'/'.$targetArg;
+
+ if (!is_dir($targetArg)) {
+ throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
+ }
}
$this->filesystem = $this->getContainer()->get('filesystem');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
index f926b4153bcd5..49284270e6e34 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
@@ -54,7 +54,6 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $outputIsVerbose = $output->isVerbose();
$io = new SymfonyStyle($input, $output);
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
@@ -78,47 +77,59 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($input->getOption('no-warmup')) {
$filesystem->rename($realCacheDir, $oldCacheDir);
} else {
- // the warmup cache dir name must have the same length than the real one
- // to avoid the many problems in serialized resources files
- $realCacheDir = realpath($realCacheDir);
- $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
-
- if ($filesystem->exists($warmupDir)) {
- if ($outputIsVerbose) {
- $io->comment('Clearing outdated warmup directory...');
- }
- $filesystem->remove($warmupDir);
- }
-
- if ($outputIsVerbose) {
- $io->comment('Warming up cache...');
- }
- $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
+ @trigger_error('Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.', E_USER_DEPRECATED);
- $filesystem->rename($realCacheDir, $oldCacheDir);
- if ('\\' === DIRECTORY_SEPARATOR) {
- sleep(1); // workaround for Windows PHP rename bug
- }
- $filesystem->rename($warmupDir, $realCacheDir);
+ $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
}
- if ($outputIsVerbose) {
+ if ($output->isVerbose()) {
$io->comment('Removing old cache directory...');
}
$filesystem->remove($oldCacheDir);
- if ($outputIsVerbose) {
+ if ($output->isVerbose()) {
$io->comment('Finished');
}
$io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
}
+ private function warmupCache(InputInterface $input, OutputInterface $output, $realCacheDir, $oldCacheDir)
+ {
+ $filesystem = $this->getContainer()->get('filesystem');
+ $io = new SymfonyStyle($input, $output);
+
+ // the warmup cache dir name must have the same length than the real one
+ // to avoid the many problems in serialized resources files
+ $realCacheDir = realpath($realCacheDir);
+ $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
+
+ if ($filesystem->exists($warmupDir)) {
+ if ($output->isVerbose()) {
+ $io->comment('Clearing outdated warmup directory...');
+ }
+ $filesystem->remove($warmupDir);
+ }
+
+ if ($output->isVerbose()) {
+ $io->comment('Warming up cache...');
+ }
+ $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
+
+ $filesystem->rename($realCacheDir, $oldCacheDir);
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ sleep(1); // workaround for Windows PHP rename bug
+ }
+ $filesystem->rename($warmupDir, $realCacheDir);
+ }
+
/**
* @param string $warmupDir
* @param string $realCacheDir
* @param bool $enableOptionalWarmers
+ *
+ * @internal to be removed in 4.0
*/
protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = true)
{
@@ -183,6 +194,8 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
* @param string $warmupDir
*
* @return KernelInterface
+ *
+ * @internal to be removed in 4.0
*/
protected function getTempKernel(KernelInterface $parent, $namespace, $parentClass, $warmupDir)
{
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
index 82934e1845fea..3ee9f086aedbc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
@@ -33,7 +33,7 @@ protected function configure()
$this
->setName('cache:pool:clear')
->setDefinition(array(
- new InputArgument('pools', InputArgument::IS_ARRAY, 'A list of cache pools or cache pool clearers'),
+ new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'),
))
->setDescription('Clears cache pools')
->setHelp(<<<'EOF'
@@ -55,16 +55,21 @@ protected function execute(InputInterface $input, OutputInterface $output)
$clearers = array();
$container = $this->getContainer();
$cacheDir = $container->getParameter('kernel.cache_dir');
+ $globalClearer = $container->get('cache.global_clearer');
foreach ($input->getArgument('pools') as $id) {
- $pool = $container->get($id);
-
- if ($pool instanceof CacheItemPoolInterface) {
- $pools[$id] = $pool;
- } elseif ($pool instanceof Psr6CacheClearer) {
- $clearers[$id] = $pool;
+ if ($globalClearer->hasPool($id)) {
+ $pools[$id] = $id;
} else {
- throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
+ $pool = $container->get($id);
+
+ if ($pool instanceof CacheItemPoolInterface) {
+ $pools[$id] = $pool;
+ } elseif ($pool instanceof Psr6CacheClearer) {
+ $clearers[$id] = $pool;
+ } else {
+ throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
+ }
}
}
@@ -75,7 +80,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
foreach ($pools as $id => $pool) {
$io->comment(sprintf('Clearing cache pool: %s ', $id));
- $pool->clear();
+
+ if ($pool instanceof CacheItemPoolInterface) {
+ $pool->clear();
+ } else {
+ $globalClearer->clearPool($id);
+ }
}
$io->success('Cache was successfully cleared.');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
index 22811c6558894..924bd8e92f659 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
@@ -62,11 +62,12 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
+ $errorIo = $io->getErrorStyle();
if (null === $name = $input->getArgument('name')) {
- $this->listBundles($io);
- $io->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. debug:config FrameworkBundle )');
- $io->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. debug:config FrameworkBundle serializer to dump the framework.serializer configuration)');
+ $this->listBundles($errorIo);
+ $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. debug:config FrameworkBundle )');
+ $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. debug:config FrameworkBundle serializer to dump the framework.serializer configuration)');
return;
}
@@ -80,10 +81,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->validateConfiguration($extension, $configuration);
- $configs = $container->getParameterBag()->resolveValue($configs);
+ $configs = $container->resolveEnvPlaceholders($container->getParameterBag()->resolveValue($configs));
$processor = new Processor();
- $config = $processor->processConfiguration($configuration, $configs);
+ $config = $container->resolveEnvPlaceholders($container->getParameterBag()->resolveValue($processor->processConfiguration($configuration, $configs)));
if (null === $path = $input->getArgument('path')) {
$io->title(
@@ -98,7 +99,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
try {
$config = $this->getConfigForPath($config, $path, $extensionAlias);
} catch (LogicException $e) {
- $io->error($e->getMessage());
+ $errorIo->error($e->getMessage());
return;
}
@@ -130,7 +131,7 @@ private function compileContainer()
*
* @return mixed
*/
- private function getConfigForPath(array $config = array(), $path, $alias)
+ private function getConfigForPath(array $config, $path, $alias)
{
$steps = explode('.', $path);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
index dfa604f7a85ae..476813fc3621e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
@@ -37,6 +37,7 @@ protected function configure()
->setName('config:dump-reference')
->setDefinition(array(
new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'),
+ new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'),
))
->setDescription('Dumps the default configuration for an extension')
@@ -55,6 +56,10 @@ protected function configure()
php %command.full_name% FrameworkBundle --format=xml
+For dumping a specific option, add its path as second argument (only available for the yaml format):
+
+ php %command.full_name% framework profiler.matcher
+
EOF
)
;
@@ -68,10 +73,14 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
+ $errorIo = $io->getErrorStyle();
if (null === $name = $input->getArgument('name')) {
- $this->listBundles($io);
- $io->comment('Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle )');
+ $this->listBundles($errorIo);
+ $errorIo->comment(array(
+ 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle )',
+ 'For dumping a specific option, add its path as the second argument of this command. (e.g. config:dump-reference FrameworkBundle profiler.matcher to dump the framework.profiler.matcher configuration)',
+ ));
return;
}
@@ -82,13 +91,26 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->validateConfiguration($extension, $configuration);
+ $format = $input->getOption('format');
+ $path = $input->getArgument('path');
+
+ if ($path !== null && 'yaml' !== $format) {
+ $errorIo->error('The "path" option is only available for the "yaml" format.');
+
+ return 1;
+ }
+
if ($name === $extension->getAlias()) {
$message = sprintf('Default configuration for extension with alias: "%s"', $name);
} else {
$message = sprintf('Default configuration for "%s"', $name);
}
- switch ($input->getOption('format')) {
+ if ($path !== null) {
+ $message .= sprintf(' at path "%s"', $path);
+ }
+
+ switch ($format) {
case 'yaml':
$io->writeln(sprintf('# %s', $message));
$dumper = new YamlReferenceDumper();
@@ -102,6 +124,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \InvalidArgumentException('Only the yaml and xml formats are supported.');
}
- $io->writeln($dumper->dump($configuration, $extension->getNamespace()));
+ $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
index 981df241cd3a1..8e8bf8ca3c0ff 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
@@ -19,6 +19,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\Config\FileLocator;
/**
@@ -43,6 +44,7 @@ protected function configure()
->setDefinition(array(
new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'),
new InputOption('show-private', null, InputOption::VALUE_NONE, 'Used to show public *and* private services'),
+ new InputOption('show-arguments', null, InputOption::VALUE_NONE, 'Used to show arguments in services'),
new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Shows all services with a specific tag'),
new InputOption('tags', null, InputOption::VALUE_NONE, 'Displays tagged services for an application'),
new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Displays a specific parameter for an application'),
@@ -92,11 +94,17 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
+ $errorIo = $io->getErrorStyle();
+
$this->validateInput($input);
$object = $this->getContainerBuilder();
if ($input->getOption('parameters')) {
- $object = $object->getParameterBag();
+ $parameters = array();
+ foreach ($object->getParameterBag()->all() as $k => $v) {
+ $parameters[$k] = $object->resolveEnvPlaceholders($v);
+ }
+ $object = new ParameterBag($parameters);
$options = array();
} elseif ($parameter = $input->getOption('parameter')) {
$options = array('parameter' => $parameter);
@@ -105,7 +113,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
} elseif ($tag = $input->getOption('tag')) {
$options = array('tag' => $tag, 'show_private' => $input->getOption('show-private'));
} elseif ($name = $input->getArgument('name')) {
- $name = $this->findProperServiceName($input, $io, $object, $name);
+ $name = $this->findProperServiceName($input, $errorIo, $object, $name);
$options = array('id' => $name);
} else {
$options = array('show_private' => $input->getOption('show-private'));
@@ -113,17 +121,18 @@ protected function execute(InputInterface $input, OutputInterface $output)
$helper = new DescriptorHelper();
$options['format'] = $input->getOption('format');
+ $options['show_arguments'] = $input->getOption('show-arguments');
$options['raw_text'] = $input->getOption('raw');
$options['output'] = $io;
- $helper->describe($output, $object, $options);
+ $helper->describe($io, $object, $options);
if (!$input->getArgument('name') && !$input->getOption('tag') && !$input->getOption('parameter') && $input->isInteractive()) {
if ($input->getOption('tags')) {
- $io->comment('To search for a specific tag, re-run this command with a search term. (e.g. debug:container --tag=form.type )');
+ $errorIo->comment('To search for a specific tag, re-run this command with a search term. (e.g. debug:container --tag=form.type )');
} elseif ($input->getOption('parameters')) {
- $io->comment('To search for a specific parameter, re-run this command with a search term. (e.g. debug:container --parameter=kernel.debug )');
+ $errorIo->comment('To search for a specific parameter, re-run this command with a search term. (e.g. debug:container --parameter=kernel.debug )');
} else {
- $io->comment('To search for a specific service, re-run this command with a search term. (e.g. debug:container log )');
+ $errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. debug:container log )');
}
}
}
@@ -168,11 +177,11 @@ protected function getContainerBuilder()
}
if (!$this->getApplication()->getKernel()->isDebug()) {
- throw new \LogicException(sprintf('Debug information about the container is only available in debug mode.'));
+ throw new \LogicException('Debug information about the container is only available in debug mode.');
}
if (!is_file($cachedFile = $this->getContainer()->getParameter('debug.container.dump'))) {
- throw new \LogicException(sprintf('Debug information about the container could not be found. Please clear the cache and try again.'));
+ throw new \LogicException('Debug information about the container could not be found. Please clear the cache and try again.');
}
$container = new ContainerBuilder();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
index 2eb310ddf1701..ef1c3017fca28 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
@@ -65,7 +65,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$options = array();
if ($event = $input->getArgument('event')) {
if (!$dispatcher->hasListeners($event)) {
- $io->warning(sprintf('The event "%s" does not have any registered listeners.', $event));
+ $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event));
return;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
index 97707e8798b59..22f0bc6795d5b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
@@ -17,6 +17,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Route;
@@ -85,13 +86,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
}
- $this->convertController($route);
+ $callable = $this->extractCallable($route);
$helper->describe($io, $route, array(
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'name' => $name,
'output' => $io,
+ 'callable' => $callable,
));
} else {
foreach ($routes as $route) {
@@ -109,12 +111,38 @@ protected function execute(InputInterface $input, OutputInterface $output)
private function convertController(Route $route)
{
- $nameParser = $this->getContainer()->get('controller_name_converter');
if ($route->hasDefault('_controller')) {
+ $nameParser = $this->getContainer()->get('controller_name_converter');
try {
$route->setDefault('_controller', $nameParser->build($route->getDefault('_controller')));
} catch (\InvalidArgumentException $e) {
}
}
}
+
+ private function extractCallable(Route $route)
+ {
+ if (!$route->hasDefault('_controller')) {
+ return;
+ }
+
+ $controller = $route->getDefault('_controller');
+
+ if (1 === substr_count($controller, ':')) {
+ list($service, $method) = explode(':', $controller);
+ try {
+ return sprintf('%s::%s', get_class($this->getContainer()->get($service)), $method);
+ } catch (ServiceNotFoundException $e) {
+ }
+ }
+
+ $nameParser = $this->getContainer()->get('controller_name_converter');
+ try {
+ $shortNotation = $nameParser->build($controller);
+ $route->setDefault('_controller', $shortNotation);
+
+ return $controller;
+ } catch (\InvalidArgumentException $e) {
+ }
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php
deleted file mode 100644
index ccfa5dde6b7e8..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php
+++ /dev/null
@@ -1,69 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Command;
-
-/**
- * Base methods for commands related to PHP's built-in web server.
- *
- * @author Christian Flothmann
- */
-abstract class ServerCommand extends ContainerAwareCommand
-{
- /**
- * {@inheritdoc}
- */
- public function isEnabled()
- {
- if (defined('HHVM_VERSION')) {
- return false;
- }
-
- if (!class_exists('Symfony\Component\Process\Process')) {
- return false;
- }
-
- return parent::isEnabled();
- }
-
- /**
- * Determines the name of the lock file for a particular PHP web server process.
- *
- * @param string $address An address/port tuple
- *
- * @return string The filename
- */
- protected function getLockFile($address)
- {
- return sys_get_temp_dir().'/'.strtr($address, '.:', '--').'.pid';
- }
-
- protected function isOtherServerProcessRunning($address)
- {
- $lockFile = $this->getLockFile($address);
-
- if (file_exists($lockFile)) {
- return true;
- }
-
- list($hostname, $port) = explode(':', $address);
-
- $fp = @fsockopen($hostname, $port, $errno, $errstr, 5);
-
- if (false !== $fp) {
- fclose($fp);
-
- return true;
- }
-
- return false;
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php
deleted file mode 100644
index e7dec312f99ba..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php
+++ /dev/null
@@ -1,175 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Command;
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Output\ConsoleOutputInterface;
-use Symfony\Component\Console\Style\SymfonyStyle;
-use Symfony\Component\Process\PhpExecutableFinder;
-use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ProcessBuilder;
-use Symfony\Component\Process\Exception\RuntimeException;
-
-/**
- * Runs Symfony application using PHP built-in web server.
- *
- * @author Michał Pipa
- */
-class ServerRunCommand extends ServerCommand
-{
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this
- ->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
- new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
- new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
- new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
- ))
- ->setName('server:run')
- ->setDescription('Runs PHP built-in web server')
- ->setHelp(<<<'EOF'
-The %command.name% runs PHP built-in web server:
-
- %command.full_name%
-
-To change default bind address and port use the address argument:
-
- %command.full_name% 127.0.0.1:8080
-
-To change default docroot directory use the --docroot option:
-
- %command.full_name% --docroot=htdocs/
-
-If you have custom docroot directory layout, you can specify your own
-router script using --router option:
-
- %command.full_name% --router=app/config/router.php
-
-Specifing a router script is required when the used environment is not "dev",
-"prod", or "test".
-
-See also: http://www.php.net/manual/en/features.commandline.webserver.php
-
-EOF
- )
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = new SymfonyStyle($input, $output);
- $documentRoot = $input->getOption('docroot');
-
- if (null === $documentRoot) {
- $documentRoot = $this->getContainer()->getParameter('kernel.root_dir').'/../web';
- }
-
- if (!is_dir($documentRoot)) {
- $io->error(sprintf('The given document root directory "%s" does not exist', $documentRoot));
-
- return 1;
- }
-
- $env = $this->getContainer()->getParameter('kernel.environment');
- $address = $input->getArgument('address');
-
- if (false === strpos($address, ':')) {
- $address = $address.':'.$input->getOption('port');
- }
-
- if ($this->isOtherServerProcessRunning($address)) {
- $io->error(sprintf('A process is already listening on http://%s.', $address));
-
- return 1;
- }
-
- if ('prod' === $env) {
- $io->error('Running PHP built-in server in production environment is NOT recommended!');
- }
-
- $io->success(sprintf('Server running on http://%s', $address));
- $io->comment('Quit the server with CONTROL-C.');
-
- if (null === $builder = $this->createPhpProcessBuilder($io, $address, $input->getOption('router'), $env)) {
- return 1;
- }
-
- $builder->setWorkingDirectory($documentRoot);
- $builder->setTimeout(null);
- $process = $builder->getProcess();
- $callback = null;
-
- if (OutputInterface::VERBOSITY_NORMAL > $output->getVerbosity()) {
- $process->disableOutput();
- } else {
- try {
- $process->setTty(true);
- } catch (RuntimeException $e) {
- $callback = function ($type, $buffer) use ($output) {
- if (Process::ERR === $type && $output instanceof ConsoleOutputInterface) {
- $output = $output->getErrorOutput();
- }
- $output->write($buffer, false, OutputInterface::OUTPUT_RAW);
- };
- }
- }
- $process->run($callback);
-
- if (!$process->isSuccessful()) {
- $errorMessages = array('Built-in server terminated unexpectedly.');
-
- if ($process->isOutputDisabled()) {
- $errorMessages[] = 'Run the command again with -v option for more details.';
- }
-
- $io->error($errorMessages);
- }
-
- return $process->getExitCode();
- }
-
- private function createPhpProcessBuilder(SymfonyStyle $io, $address, $router, $env)
- {
- $router = $router ?: $this
- ->getContainer()
- ->get('kernel')
- ->locateResource(sprintf('@FrameworkBundle/Resources/config/router_%s.php', $env))
- ;
-
- if (!file_exists($router)) {
- $io->error(sprintf('The given router script "%s" does not exist.', $router));
-
- return;
- }
-
- $router = realpath($router);
- $finder = new PhpExecutableFinder();
-
- if (false === $binary = $finder->find()) {
- $io->error('Unable to find PHP binary to run server.');
-
- return;
- }
-
- return new ProcessBuilder(array($binary, '-S', $address, $router));
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php
deleted file mode 100644
index 5e2f273ac8784..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php
+++ /dev/null
@@ -1,234 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Command;
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Style\SymfonyStyle;
-use Symfony\Component\Process\PhpExecutableFinder;
-use Symfony\Component\Process\Process;
-
-/**
- * Runs PHP's built-in web server in a background process.
- *
- * @author Christian Flothmann
- */
-class ServerStartCommand extends ServerCommand
-{
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this
- ->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
- new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
- new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
- new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
- new InputOption('force', 'f', InputOption::VALUE_NONE, 'Force web server startup'),
- ))
- ->setName('server:start')
- ->setDescription('Starts PHP built-in web server in the background')
- ->setHelp(<<<'EOF'
-The %command.name% runs PHP's built-in web server:
-
- php %command.full_name%
-
-To change the default bind address and the default port use the address argument:
-
- php %command.full_name% 127.0.0.1:8080
-
-To change the default document root directory use the --docroot option:
-
- php %command.full_name% --docroot=htdocs/
-
-If you have a custom document root directory layout, you can specify your own
-router script using the --router option:
-
- php %command.full_name% --router=app/config/router.php
-
-Specifying a router script is required when the used environment is not "dev" or
-"prod" .
-
-See also: http://www.php.net/manual/en/features.commandline.webserver.php
-
-EOF
- )
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = new SymfonyStyle($input, $cliOutput = $output);
-
- if (!extension_loaded('pcntl')) {
- $io->error(array(
- 'This command needs the pcntl extension to run.',
- 'You can either install it or use the "server:run" command instead to run the built-in web server.',
- ));
-
- if ($io->ask('Do you want to execute server:run immediately? [Yn] ', true)) {
- $command = $this->getApplication()->find('server:run');
-
- return $command->run($input, $cliOutput);
- }
-
- return 1;
- }
-
- $documentRoot = $input->getOption('docroot');
-
- if (null === $documentRoot) {
- $documentRoot = $this->getContainer()->getParameter('kernel.root_dir').'/../web';
- }
-
- if (!is_dir($documentRoot)) {
- $io->error(sprintf('The given document root directory "%s" does not exist.', $documentRoot));
-
- return 1;
- }
-
- $env = $this->getContainer()->getParameter('kernel.environment');
-
- if (false === $router = $this->determineRouterScript($input->getOption('router'), $env, $io)) {
- return 1;
- }
-
- $address = $input->getArgument('address');
-
- if (false === strpos($address, ':')) {
- $address = $address.':'.$input->getOption('port');
- }
-
- if (!$input->getOption('force') && $this->isOtherServerProcessRunning($address)) {
- $io->error(array(
- sprintf('A process is already listening on http://%s.', $address),
- 'Use the --force option if the server process terminated unexpectedly to start a new web server process.',
- ));
-
- return 1;
- }
-
- if ('prod' === $env) {
- $io->error('Running PHP built-in server in production environment is NOT recommended!');
- }
-
- $pid = pcntl_fork();
-
- if ($pid < 0) {
- $io->error('Unable to start the server process.');
-
- return 1;
- }
-
- if ($pid > 0) {
- $io->success(sprintf('Web server listening on http://%s', $address));
-
- return;
- }
-
- if (posix_setsid() < 0) {
- $io->error('Unable to set the child process as session leader');
-
- return 1;
- }
-
- if (null === $process = $this->createServerProcess($io, $address, $documentRoot, $router)) {
- return 1;
- }
-
- $process->disableOutput();
- $process->start();
- $lockFile = $this->getLockFile($address);
- touch($lockFile);
-
- if (!$process->isRunning()) {
- $io->error('Unable to start the server process');
- unlink($lockFile);
-
- return 1;
- }
-
- // stop the web server when the lock file is removed
- while ($process->isRunning()) {
- if (!file_exists($lockFile)) {
- $process->stop();
- }
-
- sleep(1);
- }
- }
-
- /**
- * Determine the absolute file path for the router script, using the environment to choose a standard script
- * if no custom router script is specified.
- *
- * @param string|null $router File path of the custom router script, if set by the user; otherwise null
- * @param string $env The application environment
- * @param SymfonyStyle $io An SymfonyStyle instance
- *
- * @return string|bool The absolute file path of the router script, or false on failure
- */
- private function determineRouterScript($router, $env, SymfonyStyle $io)
- {
- if (null === $router) {
- $router = $this
- ->getContainer()
- ->get('kernel')
- ->locateResource(sprintf('@FrameworkBundle/Resources/config/router_%s.php', $env))
- ;
- }
-
- if (false === $path = realpath($router)) {
- $io->error(sprintf('The given router script "%s" does not exist.', $router));
-
- return false;
- }
-
- return $path;
- }
-
- /**
- * Creates a process to start PHP's built-in web server.
- *
- * @param SymfonyStyle $io A SymfonyStyle instance
- * @param string $address IP address and port to listen to
- * @param string $documentRoot The application's document root
- * @param string $router The router filename
- *
- * @return Process The process
- */
- private function createServerProcess(SymfonyStyle $io, $address, $documentRoot, $router)
- {
- $finder = new PhpExecutableFinder();
- if (false === $binary = $finder->find()) {
- $io->error('Unable to find PHP binary to start server.');
-
- return;
- }
-
- $script = implode(' ', array_map(array('Symfony\Component\Process\ProcessUtils', 'escapeArgument'), array(
- $binary,
- '-S',
- $address,
- $router,
- )));
-
- return new Process('exec '.$script, $documentRoot, null, null, null);
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
deleted file mode 100644
index d7cb9e7d08197..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
+++ /dev/null
@@ -1,79 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Command;
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Style\SymfonyStyle;
-
-/**
- * Shows the status of a process that is running PHP's built-in web server in
- * the background.
- *
- * @author Christian Flothmann
- */
-class ServerStatusCommand extends ServerCommand
-{
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this
- ->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
- new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
- ))
- ->setName('server:status')
- ->setDescription('Outputs the status of the built-in web server for the given address')
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = new SymfonyStyle($input, $output);
- $address = $input->getArgument('address');
-
- if (false === strpos($address, ':')) {
- $address = $address.':'.$input->getOption('port');
- }
-
- // remove an orphaned lock file
- if (file_exists($this->getLockFile($address)) && !$this->isServerRunning($address)) {
- unlink($this->getLockFile($address));
- }
-
- if (file_exists($this->getLockFile($address))) {
- $io->success(sprintf('Web server still listening on http://%s', $address));
- } else {
- $io->warning(sprintf('No web server is listening on http://%s', $address));
- }
- }
-
- private function isServerRunning($address)
- {
- list($hostname, $port) = explode(':', $address);
-
- if (false !== $fp = @fsockopen($hostname, $port, $errno, $errstr, 1)) {
- fclose($fp);
-
- return true;
- }
-
- return false;
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php
deleted file mode 100644
index 8f79978a9a845..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php
+++ /dev/null
@@ -1,76 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Command;
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Style\SymfonyStyle;
-
-/**
- * Stops a background process running PHP's built-in web server.
- *
- * @author Christian Flothmann
- */
-class ServerStopCommand extends ServerCommand
-{
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $this
- ->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
- new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
- ))
- ->setName('server:stop')
- ->setDescription('Stops PHP\'s built-in web server that was started with the server:start command')
- ->setHelp(<<<'EOF'
-The %command.name% stops PHP's built-in web server:
-
- php %command.full_name%
-
-To change the default bind address and the default port use the address argument:
-
- php %command.full_name% 127.0.0.1:8080
-
-EOF
- )
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = new SymfonyStyle($input, $output);
-
- $address = $input->getArgument('address');
- if (false === strpos($address, ':')) {
- $address = $address.':'.$input->getOption('port');
- }
-
- $lockFile = $this->getLockFile($address);
-
- if (!file_exists($lockFile)) {
- $io->error(sprintf('No web server is listening on http://%s', $address));
-
- return 1;
- }
-
- unlink($lockFile);
- $io->success(sprintf('Stopped the web server listening on http://%s', $address));
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
index 299045d126b32..79b4234d81eb8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
@@ -159,7 +159,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$outputMessage .= sprintf(' and domain "%s"', $domain);
}
- $io->warning($outputMessage);
+ $io->getErrorStyle()->warning($outputMessage);
return;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
index c2083e034e32c..f88747cfa61f8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
@@ -85,10 +85,11 @@ public function isEnabled()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
+ $errorIo = $io->getErrorStyle();
// check presence of force or dump-message
if ($input->getOption('force') !== true && $input->getOption('dump-messages') !== true) {
- $io->error('You must choose one of --force or --dump-messages');
+ $errorIo->error('You must choose one of --force or --dump-messages');
return 1;
}
@@ -97,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$writer = $this->getContainer()->get('translation.writer');
$supportedFormats = $writer->getFormats();
if (!in_array($input->getOption('output-format'), $supportedFormats)) {
- $io->error(array('Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).'.'));
+ $errorIo->error(array('Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).'.'));
return 1;
}
@@ -127,12 +128,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- $io->title('Translation Messages Extractor and Dumper');
- $io->comment(sprintf('Generating "%s " translation files for "%s "', $input->getArgument('locale'), $currentName));
+ $errorIo->title('Translation Messages Extractor and Dumper');
+ $errorIo->comment(sprintf('Generating "%s " translation files for "%s "', $input->getArgument('locale'), $currentName));
// load any messages from templates
$extractedCatalogue = new MessageCatalogue($input->getArgument('locale'));
- $io->comment('Parsing templates...');
+ $errorIo->comment('Parsing templates...');
$extractor = $this->getContainer()->get('translation.extractor');
$extractor->setPrefix($input->getOption('no-prefix') ? '' : $input->getOption('prefix'));
foreach ($transPaths as $path) {
@@ -144,7 +145,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// load any existing messages from the translation files
$currentCatalogue = new MessageCatalogue($input->getArgument('locale'));
- $io->comment('Loading translation files...');
+ $errorIo->comment('Loading translation files...');
$loader = $this->getContainer()->get('translation.loader');
foreach ($transPaths as $path) {
$path .= 'translations';
@@ -165,7 +166,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// Exit if no messages found.
if (!count($operation->getDomains())) {
- $io->warning('No translation messages were found.');
+ $errorIo->warning('No translation messages were found.');
return;
}
@@ -199,7 +200,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if ($input->getOption('output-format') == 'xlf') {
- $io->comment('Xliff output version is 1.2 ');
+ $errorIo->comment('Xliff output version is 1.2 ');
}
$resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was');
@@ -211,7 +212,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// save the files
if ($input->getOption('force') === true) {
- $io->comment('Writing files...');
+ $errorIo->comment('Writing files...');
$bundleTransPath = false;
foreach ($transPaths as $path) {
@@ -232,7 +233,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- $io->success($resultMessage.'.');
+ $errorIo->success($resultMessage.'.');
}
private function filterCatalogue(MessageCatalogue $catalogue, $domain)
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
index 40604e3d809db..0287f42a8ed4d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
@@ -17,7 +17,6 @@
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper;
use Symfony\Component\Workflow\Marking;
-use Symfony\Component\Workflow\Workflow;
/**
* @author Grégoire Pineau
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php
new file mode 100644
index 0000000000000..dcc3eb3abe2d5
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand;
+
+/**
+ * Validates XLIFF files syntax and outputs encountered errors.
+ *
+ * @author Grégoire Pineau
+ * @author Robin Chalas
+ * @author Javier Eguiluz
+ */
+class XliffLintCommand extends Command
+{
+ private $command;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this->setName('lint:xliff');
+
+ if (!$this->isEnabled()) {
+ return;
+ }
+
+ $directoryIteratorProvider = function ($directory, $default) {
+ if (!is_dir($directory)) {
+ $directory = $this->getApplication()->getKernel()->locateResource($directory);
+ }
+
+ return $default($directory);
+ };
+
+ $isReadableProvider = function ($fileOrDirectory, $default) {
+ return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory);
+ };
+
+ $this->command = new BaseLintCommand(null, $directoryIteratorProvider, $isReadableProvider);
+
+ $this
+ ->setDescription($this->command->getDescription())
+ ->setDefinition($this->command->getDefinition())
+ ->setHelp($this->command->getHelp().<<<'EOF'
+
+Or find all files in a bundle:
+
+ php %command.full_name% @AcmeDemoBundle
+
+EOF
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isEnabled()
+ {
+ return class_exists(BaseLintCommand::class);
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ return $this->command->execute($input, $output);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
index 5dfe21357f46a..da28fc0294af2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
@@ -80,6 +80,16 @@ public function doRun(InputInterface $input, OutputInterface $output)
return parent::doRun($input, $output);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function find($name)
+ {
+ $this->registerCommands();
+
+ return parent::find($name);
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php
index da809aea8df63..c081dfc6e96c6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php
@@ -54,10 +54,10 @@ public function describe(OutputInterface $output, $object, array $options = arra
$this->describeContainerTags($object, $options);
break;
case $object instanceof ContainerBuilder && isset($options['id']):
- $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options);
+ $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options, $object);
break;
case $object instanceof ContainerBuilder && isset($options['parameter']):
- $this->describeContainerParameter($object->getParameter($options['parameter']), $options);
+ $this->describeContainerParameter($object->resolveEnvPlaceholders($object->getParameter($options['parameter'])), $options);
break;
case $object instanceof ContainerBuilder:
$this->describeContainerServices($object, $options);
@@ -140,8 +140,9 @@ abstract protected function describeContainerTags(ContainerBuilder $builder, arr
*
* @param Definition|Alias|object $service
* @param array $options
+ * @param ContainerBuilder|null $builder
*/
- abstract protected function describeContainerService($service, array $options = array());
+ abstract protected function describeContainerService($service, array $options = array(), ContainerBuilder $builder = null);
/**
* Describes container services.
@@ -165,10 +166,11 @@ abstract protected function describeContainerDefinition(Definition $definition,
/**
* Describes a service alias.
*
- * @param Alias $alias
- * @param array $options
+ * @param Alias $alias
+ * @param array $options
+ * @param ContainerBuilder|null $builder
*/
- abstract protected function describeContainerAlias(Alias $alias, array $options = array());
+ abstract protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null);
/**
* Describes a container parameter.
@@ -309,4 +311,15 @@ protected function sortServiceIds(array $serviceIds)
return $serviceIds;
}
+
+ protected function formatClosure(\Closure $closure)
+ {
+ $r = new \ReflectionFunction($closure);
+
+ if (preg_match('#^/\*\* @closure-proxy ([^: ]++)::([^: ]++) \*/$#', $r->getDocComment(), $m)) {
+ return sprintf('%s::%s', $m[1], $m[2]);
+ }
+
+ return 'closure';
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
index 99adb3831b776..0b374855a72c5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
@@ -12,6 +12,8 @@
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -77,16 +79,16 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
/**
* {@inheritdoc}
*/
- protected function describeContainerService($service, array $options = array())
+ protected function describeContainerService($service, array $options = array(), ContainerBuilder $builder = null)
{
if (!isset($options['id'])) {
throw new \InvalidArgumentException('An "id" option must be provided.');
}
if ($service instanceof Alias) {
- $this->writeData($this->getContainerAliasData($service), $options);
+ $this->describeContainerAlias($service, $options, $builder);
} elseif ($service instanceof Definition) {
- $this->writeData($this->getContainerDefinitionData($service), $options);
+ $this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options);
} else {
$this->writeData(get_class($service), $options);
}
@@ -99,6 +101,8 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
{
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
$showPrivate = isset($options['show_private']) && $options['show_private'];
+ $omitTags = isset($options['omit_tags']) && $options['omit_tags'];
+ $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
$data = array('definitions' => array(), 'aliases' => array(), 'services' => array());
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
@@ -108,7 +112,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
$data['aliases'][$serviceId] = $this->getContainerAliasData($service);
} elseif ($service instanceof Definition) {
if (($showPrivate || $service->isPublic())) {
- $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service);
+ $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments);
}
} else {
$data['services'][$serviceId] = get_class($service);
@@ -123,15 +127,22 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
*/
protected function describeContainerDefinition(Definition $definition, array $options = array())
{
- $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags']), $options);
+ $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options);
}
/**
* {@inheritdoc}
*/
- protected function describeContainerAlias(Alias $alias, array $options = array())
+ protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null)
{
- $this->writeData($this->getContainerAliasData($alias), $options);
+ if (!$builder) {
+ return $this->writeData($this->getContainerAliasData($alias), $options);
+ }
+
+ $this->writeData(
+ array($this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])),
+ array_merge($options, array('id' => (string) $alias))
+ );
}
/**
@@ -201,28 +212,25 @@ protected function getRouteData(Route $route)
*
* @return array
*/
- private function getContainerDefinitionData(Definition $definition, $omitTags = false)
+ private function getContainerDefinitionData(Definition $definition, $omitTags = false, $showArguments = false)
{
$data = array(
'class' => (string) $definition->getClass(),
'public' => $definition->isPublic(),
'synthetic' => $definition->isSynthetic(),
'lazy' => $definition->isLazy(),
+ 'shared' => $definition->isShared(),
+ 'abstract' => $definition->isAbstract(),
+ 'autowire' => $definition->isAutowired(),
+ 'autoconfigure' => $definition->isAutoconfigured(),
);
- if (method_exists($definition, 'isShared')) {
- $data['shared'] = $definition->isShared();
+ foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
+ $data['autowiring_types'][] = $autowiringType;
}
- $data['abstract'] = $definition->isAbstract();
-
- if (method_exists($definition, 'isAutowired')) {
- $data['autowire'] = $definition->isAutowired();
-
- $data['autowiring_types'] = array();
- foreach ($definition->getAutowiringTypes() as $autowiringType) {
- $data['autowiring_types'][] = $autowiringType;
- }
+ if ($showArguments) {
+ $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments);
}
$data['file'] = $definition->getFile();
@@ -252,11 +260,9 @@ private function getContainerDefinitionData(Definition $definition, $omitTags =
if (!$omitTags) {
$data['tags'] = array();
- if (count($definition->getTags())) {
- foreach ($definition->getTags() as $tagName => $tagData) {
- foreach ($tagData as $parameters) {
- $data['tags'][] = array('name' => $tagName, 'parameters' => $parameters);
- }
+ foreach ($definition->getTags() as $tagName => $tagData) {
+ foreach ($tagData as $parameters) {
+ $data['tags'][] = array('name' => $tagName, 'parameters' => $parameters);
}
}
}
@@ -358,7 +364,7 @@ private function getCallableData($callable, array $options = array())
}
if ($callable instanceof \Closure) {
- $data['type'] = 'closure';
+ $data['type'] = $this->formatClosure($callable);
return $data;
}
@@ -372,4 +378,37 @@ private function getCallableData($callable, array $options = array())
throw new \InvalidArgumentException('Callable is not describable.');
}
+
+ private function describeValue($value, $omitTags, $showArguments)
+ {
+ if (is_array($value)) {
+ $data = array();
+ foreach ($value as $k => $v) {
+ $data[$k] = $this->describeValue($v, $omitTags, $showArguments);
+ }
+
+ return $data;
+ }
+
+ if ($value instanceof ServiceClosureArgument) {
+ $value = $value->getValues()[0];
+ }
+
+ if ($value instanceof Reference) {
+ return array(
+ 'type' => 'service',
+ 'id' => (string) $value,
+ );
+ }
+
+ if ($value instanceof ArgumentInterface) {
+ return $this->describeValue($value->getValues(), $omitTags, $showArguments);
+ }
+
+ if ($value instanceof Definition) {
+ return $this->getContainerDefinitionData($value, $omitTags, $showArguments);
+ }
+
+ return $value;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
index 5c91fa3bf9ad2..d44d577950729 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
@@ -97,16 +97,16 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
/**
* {@inheritdoc}
*/
- protected function describeContainerService($service, array $options = array())
+ protected function describeContainerService($service, array $options = array(), ContainerBuilder $builder = null)
{
if (!isset($options['id'])) {
throw new \InvalidArgumentException('An "id" option must be provided.');
}
- $childOptions = array('id' => $options['id'], 'as_array' => true);
+ $childOptions = array_merge($options, array('id' => $options['id'], 'as_array' => true));
if ($service instanceof Alias) {
- $this->describeContainerAlias($service, $childOptions);
+ $this->describeContainerAlias($service, $childOptions, $builder);
} elseif ($service instanceof Definition) {
$this->describeContainerDefinition($service, $childOptions);
} else {
@@ -129,6 +129,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
$showPrivate = isset($options['show_private']) && $options['show_private'];
+ $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
$services = array('definitions' => array(), 'aliases' => array(), 'services' => array());
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
@@ -149,7 +150,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
$this->write("\n\nDefinitions\n-----------\n");
foreach ($services['definitions'] as $id => $service) {
$this->write("\n");
- $this->describeContainerDefinition($service, array('id' => $id));
+ $this->describeContainerDefinition($service, array('id' => $id, 'show_arguments' => $showArguments));
}
}
@@ -179,20 +180,18 @@ protected function describeContainerDefinition(Definition $definition, array $op
."\n".'- Public: '.($definition->isPublic() ? 'yes' : 'no')
."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no')
."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no')
+ ."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no')
+ ."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no')
+ ."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no')
+ ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no')
;
- if (method_exists($definition, 'isShared')) {
- $output .= "\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no');
+ foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
+ $output .= "\n".'- Autowiring Type: `'.$autowiringType.'`';
}
- $output .= "\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no');
-
- if (method_exists($definition, 'isAutowired')) {
- $output .= "\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no');
-
- foreach ($definition->getAutowiringTypes() as $autowiringType) {
- $output .= "\n".'- Autowiring Type: `'.$autowiringType.'`';
- }
+ if (isset($options['show_arguments']) && $options['show_arguments']) {
+ $output .= "\n".'- Arguments: '.($definition->getArguments() ? 'yes' : 'no');
}
if ($definition->getFile()) {
@@ -230,18 +229,29 @@ protected function describeContainerDefinition(Definition $definition, array $op
}
}
- $this->write(isset($options['id']) ? sprintf("%s\n%s\n\n%s\n", $options['id'], str_repeat('~', strlen($options['id'])), $output) : $output);
+ $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output);
}
/**
* {@inheritdoc}
*/
- protected function describeContainerAlias(Alias $alias, array $options = array())
+ protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null)
{
$output = '- Service: `'.$alias.'`'
."\n".'- Public: '.($alias->isPublic() ? 'yes' : 'no');
- $this->write(isset($options['id']) ? sprintf("%s\n%s\n\n%s\n", $options['id'], str_repeat('~', strlen($options['id'])), $output) : $output);
+ if (!isset($options['id'])) {
+ return $this->write($output);
+ }
+
+ $this->write(sprintf("### %s\n\n%s\n", $options['id'], $output));
+
+ if (!$builder) {
+ return;
+ }
+
+ $this->write("\n");
+ $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, array('id' => (string) $alias)));
}
/**
@@ -334,7 +344,8 @@ protected function describeCallable($callable, array $options = array())
}
if ($callable instanceof \Closure) {
- $string .= "\n- Type: `closure`";
+ $formatted = $this->formatClosure($callable);
+ $string .= "\n- Type: `$formatted`";
return $this->write($string."\n");
}
@@ -356,7 +367,7 @@ protected function describeCallable($callable, array $options = array())
*/
private function formatRouterConfig(array $array)
{
- if (!count($array)) {
+ if (!$array) {
return 'NONE';
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
index 7d876eb71336a..7aae3d3c198bb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
@@ -14,6 +14,9 @@
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -92,6 +95,9 @@ protected function describeRoute(Route $route, array $options = array())
array('Defaults', $this->formatRouterConfig($route->getDefaults())),
array('Options', $this->formatRouterConfig($route->getOptions())),
);
+ if (isset($options['callable'])) {
+ $tableRows[] = array('Callable', $options['callable']);
+ }
$table = new Table($this->getOutput());
$table->setHeaders($tableHeaders)->setRows($tableRows);
@@ -136,14 +142,14 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
/**
* {@inheritdoc}
*/
- protected function describeContainerService($service, array $options = array())
+ protected function describeContainerService($service, array $options = array(), ContainerBuilder $builder = null)
{
if (!isset($options['id'])) {
throw new \InvalidArgumentException('An "id" option must be provided.');
}
if ($service instanceof Alias) {
- $this->describeContainerAlias($service, $options);
+ $this->describeContainerAlias($service, $options, $builder);
} elseif ($service instanceof Definition) {
$this->describeContainerDefinition($service, $options);
} else {
@@ -252,9 +258,9 @@ protected function describeContainerDefinition(Definition $definition, array $op
$tableRows[] = array('Service ID', isset($options['id']) ? $options['id'] : '-');
$tableRows[] = array('Class', $definition->getClass() ?: '-');
- $tags = $definition->getTags();
- if (count($tags)) {
- $tagInformation = '';
+ $omitTags = isset($options['omit_tags']) && $options['omit_tags'];
+ if (!$omitTags && ($tags = $definition->getTags())) {
+ $tagInformation = array();
foreach ($tags as $tagName => $tagData) {
foreach ($tagData as $tagParameters) {
$parameters = array_map(function ($key, $value) {
@@ -263,12 +269,13 @@ protected function describeContainerDefinition(Definition $definition, array $op
$parameters = implode(', ', $parameters);
if ('' === $parameters) {
- $tagInformation .= sprintf('%s', $tagName);
+ $tagInformation[] = sprintf('%s', $tagName);
} else {
- $tagInformation .= sprintf('%s (%s)', $tagName, $parameters);
+ $tagInformation[] = sprintf('%s (%s)', $tagName, $parameters);
}
}
}
+ $tagInformation = implode("\n", $tagInformation);
} else {
$tagInformation = '-';
}
@@ -286,22 +293,12 @@ protected function describeContainerDefinition(Definition $definition, array $op
$tableRows[] = array('Public', $definition->isPublic() ? 'yes' : 'no');
$tableRows[] = array('Synthetic', $definition->isSynthetic() ? 'yes' : 'no');
$tableRows[] = array('Lazy', $definition->isLazy() ? 'yes' : 'no');
- if (method_exists($definition, 'isShared')) {
- $tableRows[] = array('Shared', $definition->isShared() ? 'yes' : 'no');
- }
+ $tableRows[] = array('Shared', $definition->isShared() ? 'yes' : 'no');
$tableRows[] = array('Abstract', $definition->isAbstract() ? 'yes' : 'no');
+ $tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no');
- if (method_exists($definition, 'isAutowired')) {
- $tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no');
-
- $autowiringTypes = $definition->getAutowiringTypes();
- if (count($autowiringTypes)) {
- $autowiringTypesInformation = implode(', ', $autowiringTypes);
- } else {
- $autowiringTypesInformation = '-';
- }
-
- $tableRows[] = array('Autowiring Types', $autowiringTypesInformation);
+ if ($autowiringTypes = $definition->getAutowiringTypes(false)) {
+ $tableRows[] = array('Autowiring Types', implode(', ', $autowiringTypes));
}
if ($definition->getFile()) {
@@ -323,15 +320,45 @@ protected function describeContainerDefinition(Definition $definition, array $op
}
}
+ $showArguments = isset($options['show_arguments']) && $options['show_arguments'];
+ $argumentsInformation = array();
+ if ($showArguments && ($arguments = $definition->getArguments())) {
+ foreach ($arguments as $argument) {
+ if ($argument instanceof ServiceClosureArgument) {
+ $argument = $argument->getValues()[0];
+ }
+ if ($argument instanceof Reference) {
+ $argumentsInformation[] = sprintf('Service(%s)', (string) $argument);
+ } elseif ($argument instanceof IteratorArgument) {
+ $argumentsInformation[] = sprintf('Iterator (%d element(s))', count($argument->getValues()));
+ } elseif ($argument instanceof ClosureProxyArgument) {
+ list($reference, $method) = $argument->getValues();
+ $argumentsInformation[] = sprintf('ClosureProxy(Service(%s)::%s())', $reference, $method);
+ } elseif ($argument instanceof Definition) {
+ $argumentsInformation[] = 'Inlined Service';
+ } else {
+ $argumentsInformation[] = is_array($argument) ? sprintf('Array (%d element(s))', count($argument)) : $argument;
+ }
+ }
+
+ $tableRows[] = array('Arguments', implode("\n", $argumentsInformation));
+ }
+
$options['output']->table($tableHeaders, $tableRows);
}
/**
* {@inheritdoc}
*/
- protected function describeContainerAlias(Alias $alias, array $options = array())
+ protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null)
{
$options['output']->comment(sprintf('This service is an alias for the service %s ', (string) $alias));
+
+ if (!$builder) {
+ return;
+ }
+
+ return $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, array('id' => (string) $alias)));
}
/**
@@ -439,7 +466,13 @@ private function formatCallable($callable)
}
if ($callable instanceof \Closure) {
- return '\Closure()';
+ $formatted = $this->formatClosure($callable);
+
+ if ('closure' === $formatted) {
+ return '\Closure()';
+ }
+
+ return $formatted.'()';
}
if (method_exists($callable, '__invoke')) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
index 7d7d5f0956ed4..461a4e086f9cd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
@@ -12,6 +12,9 @@
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -62,13 +65,13 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
/**
* {@inheritdoc}
*/
- protected function describeContainerService($service, array $options = array())
+ protected function describeContainerService($service, array $options = array(), ContainerBuilder $builder = null)
{
if (!isset($options['id'])) {
throw new \InvalidArgumentException('An "id" option must be provided.');
}
- $this->writeDocument($this->getContainerServiceDocument($service, $options['id']));
+ $this->writeDocument($this->getContainerServiceDocument($service, $options['id'], $builder, isset($options['show_arguments']) && $options['show_arguments']));
}
/**
@@ -76,7 +79,7 @@ protected function describeContainerService($service, array $options = array())
*/
protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
{
- $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_private']) && $options['show_private']));
+ $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_private']) && $options['show_private'], isset($options['show_arguments']) && $options['show_arguments']));
}
/**
@@ -84,15 +87,24 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
*/
protected function describeContainerDefinition(Definition $definition, array $options = array())
{
- $this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags']));
+ $this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']));
}
/**
* {@inheritdoc}
*/
- protected function describeContainerAlias(Alias $alias, array $options = array())
+ protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null)
{
- $this->writeDocument($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null));
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null)->childNodes->item(0), true));
+
+ if (!$builder) {
+ return $this->writeDocument($dom);
+ }
+
+ $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $alias), (string) $alias)->childNodes->item(0), true));
+
+ $this->writeDocument($dom);
}
/**
@@ -187,7 +199,7 @@ private function getRouteDocument(Route $route, $name = null)
$methodXML->appendChild(new \DOMText($method));
}
- if (count($route->getDefaults())) {
+ if ($route->getDefaults()) {
$routeXML->appendChild($defaultsXML = $dom->createElement('defaults'));
foreach ($route->getDefaults() as $attribute => $value) {
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
@@ -196,16 +208,18 @@ private function getRouteDocument(Route $route, $name = null)
}
}
- if (count($route->getRequirements())) {
+ $originRequirements = $requirements = $route->getRequirements();
+ unset($requirements['_scheme'], $requirements['_method']);
+ if ($requirements) {
$routeXML->appendChild($requirementsXML = $dom->createElement('requirements'));
- foreach ($route->getRequirements() as $attribute => $pattern) {
+ foreach ($originRequirements as $attribute => $pattern) {
$requirementsXML->appendChild($requirementXML = $dom->createElement('requirement'));
$requirementXML->setAttribute('key', $attribute);
$requirementXML->appendChild(new \DOMText($pattern));
}
}
- if (count($route->getOptions())) {
+ if ($route->getOptions()) {
$routeXML->appendChild($optionsXML = $dom->createElement('options'));
foreach ($route->getOptions() as $name => $value) {
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
@@ -261,19 +275,24 @@ private function getContainerTagsDocument(ContainerBuilder $builder, $showPrivat
}
/**
- * @param mixed $service
- * @param string $id
+ * @param mixed $service
+ * @param string $id
+ * @param ContainerBuilder|null $builder
+ * @param bool $showArguments
*
* @return \DOMDocument
*/
- private function getContainerServiceDocument($service, $id)
+ private function getContainerServiceDocument($service, $id, ContainerBuilder $builder = null, $showArguments = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
if ($service instanceof Alias) {
$dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true));
+ if ($builder) {
+ $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $service), (string) $service, false, $showArguments)->childNodes->item(0), true));
+ }
} elseif ($service instanceof Definition) {
- $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id)->childNodes->item(0), true));
+ $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id, false, $showArguments)->childNodes->item(0), true));
} else {
$dom->appendChild($serviceXML = $dom->createElement('service'));
$serviceXML->setAttribute('id', $id);
@@ -287,10 +306,11 @@ private function getContainerServiceDocument($service, $id)
* @param ContainerBuilder $builder
* @param string|null $tag
* @param bool $showPrivate
+ * @param bool $showArguments
*
* @return \DOMDocument
*/
- private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false)
+ private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false, $showArguments = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($containerXML = $dom->createElement('container'));
@@ -304,7 +324,7 @@ private function getContainerServicesDocument(ContainerBuilder $builder, $tag =
continue;
}
- $serviceXML = $this->getContainerServiceDocument($service, $serviceId);
+ $serviceXML = $this->getContainerServiceDocument($service, $serviceId, null, $showArguments);
$containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true));
}
@@ -318,7 +338,7 @@ private function getContainerServicesDocument(ContainerBuilder $builder, $tag =
*
* @return \DOMDocument
*/
- private function getContainerDefinitionDocument(Definition $definition, $id = null, $omitTags = false)
+ private function getContainerDefinitionDocument(Definition $definition, $id = null, $omitTags = false, $showArguments = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($serviceXML = $dom->createElement('definition'));
@@ -349,15 +369,10 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
$serviceXML->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
$serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false');
$serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false');
- if (method_exists($definition, 'isShared')) {
- $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
- }
+ $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
$serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false');
-
- if (method_exists($definition, 'isAutowired')) {
- $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false');
- }
-
+ $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false');
+ $serviceXML->setAttribute('autoconfigured', $definition->isAutoconfigured() ? 'true' : 'false');
$serviceXML->setAttribute('file', $definition->getFile());
$calls = $definition->getMethodCalls();
@@ -369,10 +384,14 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
}
}
- if (!$omitTags) {
- $tags = $definition->getTags();
+ if ($showArguments) {
+ foreach ($this->getArgumentNodes($definition->getArguments(), $dom) as $node) {
+ $serviceXML->appendChild($node);
+ }
+ }
- if (count($tags) > 0) {
+ if (!$omitTags) {
+ if ($tags = $definition->getTags()) {
$serviceXML->appendChild($tagsXML = $dom->createElement('tags'));
foreach ($tags as $tagName => $tagData) {
foreach ($tagData as $parameters) {
@@ -391,6 +410,58 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
return $dom;
}
+ /**
+ * @param array $arguments
+ *
+ * @return \DOMNode[]
+ */
+ private function getArgumentNodes(array $arguments, \DOMDocument $dom)
+ {
+ $nodes = array();
+
+ foreach ($arguments as $argumentKey => $argument) {
+ $argumentXML = $dom->createElement('argument');
+
+ if (is_string($argumentKey)) {
+ $argumentXML->setAttribute('key', $argumentKey);
+ }
+
+ if ($argument instanceof ServiceClosureArgument) {
+ $argument = $argument->getValues()[0];
+ }
+
+ if ($argument instanceof Reference) {
+ $argumentXML->setAttribute('type', 'service');
+ $argumentXML->setAttribute('id', (string) $argument);
+ } elseif ($argument instanceof IteratorArgument) {
+ $argumentXML->setAttribute('type', 'iterator');
+
+ foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) {
+ $argumentXML->appendChild($childArgumentXML);
+ }
+ } elseif ($argument instanceof ClosureProxyArgument) {
+ list($reference, $method) = $argument->getValues();
+ $argumentXML->setAttribute('type', 'closure-proxy');
+ $argumentXML->setAttribute('id', (string) $reference);
+ $argumentXML->setAttribute('method', $method);
+ } elseif ($argument instanceof Definition) {
+ $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, false, true)->childNodes->item(0), true));
+ } elseif (is_array($argument)) {
+ $argumentXML->setAttribute('type', 'collection');
+
+ foreach ($this->getArgumentNodes($argument, $dom) as $childArgumenXML) {
+ $argumentXML->appendChild($childArgumenXML);
+ }
+ } else {
+ $argumentXML->appendChild(new \DOMText($argument));
+ }
+
+ $nodes[] = $argumentXML;
+ }
+
+ return $nodes;
+ }
+
/**
* @param Alias $alias
* @param string|null $id
@@ -523,7 +594,7 @@ private function getCallableDocument($callable)
}
if ($callable instanceof \Closure) {
- $callableXML->setAttribute('type', 'closure');
+ $callableXML->setAttribute('type', $this->formatClosure($callable));
return $dom;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php
new file mode 100644
index 0000000000000..1055b00e3b1b2
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php
@@ -0,0 +1,69 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Controller;
+
+use Psr\Container\ContainerInterface;
+use Doctrine\Common\Persistence\ManagerRegistry;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
+use Symfony\Component\Form\FormFactoryInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\Routing\RouterInterface;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
+use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
+use Symfony\Component\Serializer\SerializerInterface;
+use Symfony\Component\Templating\EngineInterface;
+
+/**
+ * Provides common features needed in controllers.
+ *
+ * @author Fabien Potencier
+ */
+abstract class AbstractController implements ServiceSubscriberInterface
+{
+ use ControllerTrait;
+
+ private $container;
+
+ /**
+ * @internal
+ * @required
+ */
+ public function setContainer(ContainerInterface $container)
+ {
+ $previous = $this->container;
+ $this->container = $container;
+
+ return $previous;
+ }
+
+ public static function getSubscribedServices()
+ {
+ return array(
+ 'router' => '?'.RouterInterface::class,
+ 'request_stack' => '?'.RequestStack::class,
+ 'http_kernel' => '?'.HttpKernelInterface::class,
+ 'serializer' => '?'.SerializerInterface::class,
+ 'session' => '?'.SessionInterface::class,
+ 'security.authorization_checker' => '?'.AuthorizationCheckerInterface::class,
+ 'templating' => '?'.EngineInterface::class,
+ 'twig' => '?'.\Twig_Environment::class,
+ 'doctrine' => '?'.ManagerRegistry::class,
+ 'form.factory' => '?'.FormFactoryInterface::class,
+ 'security.token_storage' => '?'.TokenStorageInterface::class,
+ 'security.csrf.token_manager' => '?'.CsrfTokenManagerInterface::class,
+ );
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
index 1dbf54b5adf9d..870965201e397 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
@@ -13,21 +13,6 @@
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
-use Symfony\Component\HttpFoundation\BinaryFileResponse;
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\HttpFoundation\ResponseHeaderBag;
-use Symfony\Component\HttpFoundation\StreamedResponse;
-use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\Security\Core\Exception\AccessDeniedException;
-use Symfony\Component\Security\Csrf\CsrfToken;
-use Symfony\Component\Form\Extension\Core\Type\FormType;
-use Symfony\Component\Form\Form;
-use Symfony\Component\Form\FormBuilder;
-use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
-use Doctrine\Bundle\DoctrineBundle\Registry;
/**
* Controller is a simple implementation of a Controller.
@@ -39,354 +24,7 @@
abstract class Controller implements ContainerAwareInterface
{
use ContainerAwareTrait;
-
- /**
- * Generates a URL from the given parameters.
- *
- * @param string $route The name of the route
- * @param mixed $parameters An array of parameters
- * @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
- *
- * @return string The generated URL
- *
- * @see UrlGeneratorInterface
- */
- protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
- {
- return $this->container->get('router')->generate($route, $parameters, $referenceType);
- }
-
- /**
- * Forwards the request to another controller.
- *
- * @param string $controller The controller name (a string like BlogBundle:Post:index)
- * @param array $path An array of path parameters
- * @param array $query An array of query parameters
- *
- * @return Response A Response instance
- */
- protected function forward($controller, array $path = array(), array $query = array())
- {
- $request = $this->container->get('request_stack')->getCurrentRequest();
- $path['_forwarded'] = $request->attributes;
- $path['_controller'] = $controller;
- $subRequest = $request->duplicate($query, null, $path);
-
- return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
- }
-
- /**
- * Returns a RedirectResponse to the given URL.
- *
- * @param string $url The URL to redirect to
- * @param int $status The status code to use for the Response
- *
- * @return RedirectResponse
- */
- protected function redirect($url, $status = 302)
- {
- return new RedirectResponse($url, $status);
- }
-
- /**
- * Returns a RedirectResponse to the given route with the given parameters.
- *
- * @param string $route The name of the route
- * @param array $parameters An array of parameters
- * @param int $status The status code to use for the Response
- *
- * @return RedirectResponse
- */
- protected function redirectToRoute($route, array $parameters = array(), $status = 302)
- {
- return $this->redirect($this->generateUrl($route, $parameters), $status);
- }
-
- /**
- * Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
- *
- * @param mixed $data The response data
- * @param int $status The status code to use for the Response
- * @param array $headers Array of extra headers to add
- * @param array $context Context to pass to serializer when using serializer component
- *
- * @return JsonResponse
- */
- protected function json($data, $status = 200, $headers = array(), $context = array())
- {
- if ($this->container->has('serializer')) {
- $json = $this->container->get('serializer')->serialize($data, 'json', array_merge(array(
- 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
- ), $context));
-
- return new JsonResponse($json, $status, $headers, true);
- }
-
- return new JsonResponse($data, $status, $headers);
- }
-
- /**
- * Returns a BinaryFileResponse object with original or customized file name and disposition header.
- *
- * @param \SplFileInfo|string $file File object or path to file to be sent as response
- * @param string|null $fileName File name to be sent to response or null (will use original file name)
- * @param string $disposition Disposition of response ("attachment" is default, other type is "inline")
- *
- * @return BinaryFileResponse
- */
- protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
- {
- $response = new BinaryFileResponse($file);
- $response->setContentDisposition($disposition, $fileName === null ? $response->getFile()->getFileName() : $fileName);
-
- return $response;
- }
-
- /**
- * Adds a flash message to the current session for type.
- *
- * @param string $type The type
- * @param string $message The message
- *
- * @throws \LogicException
- */
- protected function addFlash($type, $message)
- {
- if (!$this->container->has('session')) {
- throw new \LogicException('You can not use the addFlash method if sessions are disabled.');
- }
-
- $this->container->get('session')->getFlashBag()->add($type, $message);
- }
-
- /**
- * Checks if the attributes are granted against the current authentication token and optionally supplied object.
- *
- * @param mixed $attributes The attributes
- * @param mixed $object The object
- *
- * @return bool
- *
- * @throws \LogicException
- */
- protected function isGranted($attributes, $object = null)
- {
- if (!$this->container->has('security.authorization_checker')) {
- throw new \LogicException('The SecurityBundle is not registered in your application.');
- }
-
- return $this->container->get('security.authorization_checker')->isGranted($attributes, $object);
- }
-
- /**
- * Throws an exception unless the attributes are granted against the current authentication token and optionally
- * supplied object.
- *
- * @param mixed $attributes The attributes
- * @param mixed $object The object
- * @param string $message The message passed to the exception
- *
- * @throws AccessDeniedException
- */
- protected function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
- {
- if (!$this->isGranted($attributes, $object)) {
- $exception = $this->createAccessDeniedException($message);
- $exception->setAttributes($attributes);
- $exception->setSubject($object);
-
- throw $exception;
- }
- }
-
- /**
- * Returns a rendered view.
- *
- * @param string $view The view name
- * @param array $parameters An array of parameters to pass to the view
- *
- * @return string The rendered view
- */
- protected function renderView($view, array $parameters = array())
- {
- if ($this->container->has('templating')) {
- return $this->container->get('templating')->render($view, $parameters);
- }
-
- if (!$this->container->has('twig')) {
- throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available.');
- }
-
- return $this->container->get('twig')->render($view, $parameters);
- }
-
- /**
- * Renders a view.
- *
- * @param string $view The view name
- * @param array $parameters An array of parameters to pass to the view
- * @param Response $response A response instance
- *
- * @return Response A Response instance
- */
- protected function render($view, array $parameters = array(), Response $response = null)
- {
- if ($this->container->has('templating')) {
- return $this->container->get('templating')->renderResponse($view, $parameters, $response);
- }
-
- if (!$this->container->has('twig')) {
- throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.');
- }
-
- if (null === $response) {
- $response = new Response();
- }
-
- $response->setContent($this->container->get('twig')->render($view, $parameters));
-
- return $response;
- }
-
- /**
- * Streams a view.
- *
- * @param string $view The view name
- * @param array $parameters An array of parameters to pass to the view
- * @param StreamedResponse $response A response instance
- *
- * @return StreamedResponse A StreamedResponse instance
- */
- protected function stream($view, array $parameters = array(), StreamedResponse $response = null)
- {
- if ($this->container->has('templating')) {
- $templating = $this->container->get('templating');
-
- $callback = function () use ($templating, $view, $parameters) {
- $templating->stream($view, $parameters);
- };
- } elseif ($this->container->has('twig')) {
- $twig = $this->container->get('twig');
-
- $callback = function () use ($twig, $view, $parameters) {
- $twig->display($view, $parameters);
- };
- } else {
- throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available.');
- }
-
- if (null === $response) {
- return new StreamedResponse($callback);
- }
-
- $response->setCallback($callback);
-
- return $response;
- }
-
- /**
- * Returns a NotFoundHttpException.
- *
- * This will result in a 404 response code. Usage example:
- *
- * throw $this->createNotFoundException('Page not found!');
- *
- * @param string $message A message
- * @param \Exception|null $previous The previous exception
- *
- * @return NotFoundHttpException
- */
- protected function createNotFoundException($message = 'Not Found', \Exception $previous = null)
- {
- return new NotFoundHttpException($message, $previous);
- }
-
- /**
- * Returns an AccessDeniedException.
- *
- * This will result in a 403 response code. Usage example:
- *
- * throw $this->createAccessDeniedException('Unable to access this page!');
- *
- * @param string $message A message
- * @param \Exception|null $previous The previous exception
- *
- * @return AccessDeniedException
- */
- protected function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null)
- {
- return new AccessDeniedException($message, $previous);
- }
-
- /**
- * Creates and returns a Form instance from the type of the form.
- *
- * @param string $type The fully qualified class name of the form type
- * @param mixed $data The initial data for the form
- * @param array $options Options for the form
- *
- * @return Form
- */
- protected function createForm($type, $data = null, array $options = array())
- {
- return $this->container->get('form.factory')->create($type, $data, $options);
- }
-
- /**
- * Creates and returns a form builder instance.
- *
- * @param mixed $data The initial data for the form
- * @param array $options Options for the form
- *
- * @return FormBuilder
- */
- protected function createFormBuilder($data = null, array $options = array())
- {
- return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options);
- }
-
- /**
- * Shortcut to return the Doctrine Registry service.
- *
- * @return Registry
- *
- * @throws \LogicException If DoctrineBundle is not available
- */
- protected function getDoctrine()
- {
- if (!$this->container->has('doctrine')) {
- throw new \LogicException('The DoctrineBundle is not registered in your application.');
- }
-
- return $this->container->get('doctrine');
- }
-
- /**
- * Get a user from the Security Token Storage.
- *
- * @return mixed
- *
- * @throws \LogicException If SecurityBundle is not available
- *
- * @see TokenInterface::getUser()
- */
- protected function getUser()
- {
- if (!$this->container->has('security.token_storage')) {
- throw new \LogicException('The SecurityBundle is not registered in your application.');
- }
-
- if (null === $token = $this->container->get('security.token_storage')->getToken()) {
- return;
- }
-
- if (!is_object($user = $token->getUser())) {
- // e.g. anonymous authentication
- return;
- }
-
- return $user;
- }
+ use ControllerTrait;
/**
* Returns true if the service id is defined.
@@ -423,21 +61,4 @@ protected function getParameter($name)
{
return $this->container->getParameter($name);
}
-
- /**
- * Checks the validity of a CSRF token.
- *
- * @param string $id The id used when generating the token
- * @param string $token The actual token sent with the request that should be validated
- *
- * @return bool
- */
- protected function isCsrfTokenValid($id, $token)
- {
- if (!$this->container->has('security.csrf.token_manager')) {
- throw new \LogicException('CSRF protection is not enabled in your application.');
- }
-
- return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token));
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
index 31593b9b80506..355f526fdc950 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
@@ -12,18 +12,17 @@
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Psr\Log\LoggerInterface;
-use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
/**
* ControllerResolver.
*
* @author Fabien Potencier
*/
-class ControllerResolver extends BaseControllerResolver
+class ControllerResolver extends ContainerControllerResolver
{
- protected $container;
protected $parser;
/**
@@ -35,39 +34,19 @@ class ControllerResolver extends BaseControllerResolver
*/
public function __construct(ContainerInterface $container, ControllerNameParser $parser, LoggerInterface $logger = null)
{
- $this->container = $container;
$this->parser = $parser;
- parent::__construct($logger);
+ parent::__construct($container, $logger);
}
/**
- * Returns a callable for the given controller.
- *
- * @param string $controller A Controller string
- *
- * @return mixed A PHP callable
- *
- * @throws \LogicException When the name could not be parsed
- * @throws \InvalidArgumentException When the controller class does not exist
+ * {@inheritdoc}
*/
protected function createController($controller)
{
- if (false === strpos($controller, '::')) {
- $count = substr_count($controller, ':');
- if (2 == $count) {
- // controller in the a:b:c notation then
- $controller = $this->parser->parse($controller);
- } elseif (1 == $count) {
- // controller in the service:method notation
- list($service, $method) = explode(':', $controller, 2);
-
- return array($this->container->get($service), $method);
- } elseif ($this->container->has($controller) && method_exists($service = $this->container->get($controller), '__invoke')) {
- return $service;
- } else {
- throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
- }
+ if (false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
+ // controller in the a:b:c notation then
+ $controller = $this->parser->parse($controller);
}
return parent::createController($controller);
@@ -78,15 +57,14 @@ protected function createController($controller)
*/
protected function instantiateController($class)
{
- if ($this->container->has($class)) {
- return $this->container->get($class);
- }
-
$controller = parent::instantiateController($class);
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
+ if ($controller instanceof AbstractController && null !== $previousContainer = $controller->setContainer($this->container)) {
+ $controller->setContainer($previousContainer);
+ }
return $controller;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php
new file mode 100644
index 0000000000000..f138186c34d07
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php
@@ -0,0 +1,403 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Controller;
+
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\Security\Core\Exception\AccessDeniedException;
+use Symfony\Component\Security\Csrf\CsrfToken;
+use Symfony\Component\Form\Extension\Core\Type\FormType;
+use Symfony\Component\Form\Form;
+use Symfony\Component\Form\FormBuilder;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Doctrine\Bundle\DoctrineBundle\Registry;
+
+/**
+ * Common features needed in controllers.
+ *
+ * @author Fabien Potencier
+ *
+ * @internal
+ */
+trait ControllerTrait
+{
+ /**
+ * Generates a URL from the given parameters.
+ *
+ * @param string $route The name of the route
+ * @param mixed $parameters An array of parameters
+ * @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
+ *
+ * @return string The generated URL
+ *
+ * @see UrlGeneratorInterface
+ */
+ protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
+ {
+ return $this->container->get('router')->generate($route, $parameters, $referenceType);
+ }
+
+ /**
+ * Forwards the request to another controller.
+ *
+ * @param string $controller The controller name (a string like BlogBundle:Post:index)
+ * @param array $path An array of path parameters
+ * @param array $query An array of query parameters
+ *
+ * @return Response A Response instance
+ */
+ protected function forward($controller, array $path = array(), array $query = array())
+ {
+ $request = $this->container->get('request_stack')->getCurrentRequest();
+ $path['_forwarded'] = $request->attributes;
+ $path['_controller'] = $controller;
+ $subRequest = $request->duplicate($query, null, $path);
+
+ return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
+ }
+
+ /**
+ * Returns a RedirectResponse to the given URL.
+ *
+ * @param string $url The URL to redirect to
+ * @param int $status The status code to use for the Response
+ *
+ * @return RedirectResponse
+ */
+ protected function redirect($url, $status = 302)
+ {
+ return new RedirectResponse($url, $status);
+ }
+
+ /**
+ * Returns a RedirectResponse to the given route with the given parameters.
+ *
+ * @param string $route The name of the route
+ * @param array $parameters An array of parameters
+ * @param int $status The status code to use for the Response
+ *
+ * @return RedirectResponse
+ */
+ protected function redirectToRoute($route, array $parameters = array(), $status = 302)
+ {
+ return $this->redirect($this->generateUrl($route, $parameters), $status);
+ }
+
+ /**
+ * Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
+ *
+ * @param mixed $data The response data
+ * @param int $status The status code to use for the Response
+ * @param array $headers Array of extra headers to add
+ * @param array $context Context to pass to serializer when using serializer component
+ *
+ * @return JsonResponse
+ */
+ protected function json($data, $status = 200, $headers = array(), $context = array())
+ {
+ if ($this->container->has('serializer')) {
+ $json = $this->container->get('serializer')->serialize($data, 'json', array_merge(array(
+ 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
+ ), $context));
+
+ return new JsonResponse($json, $status, $headers, true);
+ }
+
+ return new JsonResponse($data, $status, $headers);
+ }
+
+ /**
+ * Returns a BinaryFileResponse object with original or customized file name and disposition header.
+ *
+ * @param \SplFileInfo|string $file File object or path to file to be sent as response
+ * @param string|null $fileName File name to be sent to response or null (will use original file name)
+ * @param string $disposition Disposition of response ("attachment" is default, other type is "inline")
+ *
+ * @return BinaryFileResponse
+ */
+ protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
+ {
+ $response = new BinaryFileResponse($file);
+ $response->setContentDisposition($disposition, $fileName === null ? $response->getFile()->getFilename() : $fileName);
+
+ return $response;
+ }
+
+ /**
+ * Adds a flash message to the current session for type.
+ *
+ * @param string $type The type
+ * @param string $message The message
+ *
+ * @throws \LogicException
+ */
+ protected function addFlash($type, $message)
+ {
+ if (!$this->container->has('session')) {
+ throw new \LogicException('You can not use the addFlash method if sessions are disabled.');
+ }
+
+ $this->container->get('session')->getFlashBag()->add($type, $message);
+ }
+
+ /**
+ * Checks if the attributes are granted against the current authentication token and optionally supplied object.
+ *
+ * @param mixed $attributes The attributes
+ * @param mixed $object The object
+ *
+ * @return bool
+ *
+ * @throws \LogicException
+ */
+ protected function isGranted($attributes, $object = null)
+ {
+ if (!$this->container->has('security.authorization_checker')) {
+ throw new \LogicException('The SecurityBundle is not registered in your application.');
+ }
+
+ return $this->container->get('security.authorization_checker')->isGranted($attributes, $object);
+ }
+
+ /**
+ * Throws an exception unless the attributes are granted against the current authentication token and optionally
+ * supplied object.
+ *
+ * @param mixed $attributes The attributes
+ * @param mixed $object The object
+ * @param string $message The message passed to the exception
+ *
+ * @throws AccessDeniedException
+ */
+ protected function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
+ {
+ if (!$this->isGranted($attributes, $object)) {
+ $exception = $this->createAccessDeniedException($message);
+ $exception->setAttributes($attributes);
+ $exception->setSubject($object);
+
+ throw $exception;
+ }
+ }
+
+ /**
+ * Returns a rendered view.
+ *
+ * @param string $view The view name
+ * @param array $parameters An array of parameters to pass to the view
+ *
+ * @return string The rendered view
+ */
+ protected function renderView($view, array $parameters = array())
+ {
+ if ($this->container->has('templating')) {
+ return $this->container->get('templating')->render($view, $parameters);
+ }
+
+ if (!$this->container->has('twig')) {
+ throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available.');
+ }
+
+ return $this->container->get('twig')->render($view, $parameters);
+ }
+
+ /**
+ * Renders a view.
+ *
+ * @param string $view The view name
+ * @param array $parameters An array of parameters to pass to the view
+ * @param Response $response A response instance
+ *
+ * @return Response A Response instance
+ */
+ protected function render($view, array $parameters = array(), Response $response = null)
+ {
+ if ($this->container->has('templating')) {
+ return $this->container->get('templating')->renderResponse($view, $parameters, $response);
+ }
+
+ if (!$this->container->has('twig')) {
+ throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.');
+ }
+
+ if (null === $response) {
+ $response = new Response();
+ }
+
+ $response->setContent($this->container->get('twig')->render($view, $parameters));
+
+ return $response;
+ }
+
+ /**
+ * Streams a view.
+ *
+ * @param string $view The view name
+ * @param array $parameters An array of parameters to pass to the view
+ * @param StreamedResponse $response A response instance
+ *
+ * @return StreamedResponse A StreamedResponse instance
+ */
+ protected function stream($view, array $parameters = array(), StreamedResponse $response = null)
+ {
+ if ($this->container->has('templating')) {
+ $templating = $this->container->get('templating');
+
+ $callback = function () use ($templating, $view, $parameters) {
+ $templating->stream($view, $parameters);
+ };
+ } elseif ($this->container->has('twig')) {
+ $twig = $this->container->get('twig');
+
+ $callback = function () use ($twig, $view, $parameters) {
+ $twig->display($view, $parameters);
+ };
+ } else {
+ throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available.');
+ }
+
+ if (null === $response) {
+ return new StreamedResponse($callback);
+ }
+
+ $response->setCallback($callback);
+
+ return $response;
+ }
+
+ /**
+ * Returns a NotFoundHttpException.
+ *
+ * This will result in a 404 response code. Usage example:
+ *
+ * throw $this->createNotFoundException('Page not found!');
+ *
+ * @param string $message A message
+ * @param \Exception|null $previous The previous exception
+ *
+ * @return NotFoundHttpException
+ */
+ protected function createNotFoundException($message = 'Not Found', \Exception $previous = null)
+ {
+ return new NotFoundHttpException($message, $previous);
+ }
+
+ /**
+ * Returns an AccessDeniedException.
+ *
+ * This will result in a 403 response code. Usage example:
+ *
+ * throw $this->createAccessDeniedException('Unable to access this page!');
+ *
+ * @param string $message A message
+ * @param \Exception|null $previous The previous exception
+ *
+ * @return AccessDeniedException
+ */
+ protected function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null)
+ {
+ return new AccessDeniedException($message, $previous);
+ }
+
+ /**
+ * Creates and returns a Form instance from the type of the form.
+ *
+ * @param string $type The fully qualified class name of the form type
+ * @param mixed $data The initial data for the form
+ * @param array $options Options for the form
+ *
+ * @return Form
+ */
+ protected function createForm($type, $data = null, array $options = array())
+ {
+ return $this->container->get('form.factory')->create($type, $data, $options);
+ }
+
+ /**
+ * Creates and returns a form builder instance.
+ *
+ * @param mixed $data The initial data for the form
+ * @param array $options Options for the form
+ *
+ * @return FormBuilder
+ */
+ protected function createFormBuilder($data = null, array $options = array())
+ {
+ return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options);
+ }
+
+ /**
+ * Shortcut to return the Doctrine Registry service.
+ *
+ * @return Registry
+ *
+ * @throws \LogicException If DoctrineBundle is not available
+ */
+ protected function getDoctrine()
+ {
+ if (!$this->container->has('doctrine')) {
+ throw new \LogicException('The DoctrineBundle is not registered in your application.');
+ }
+
+ return $this->container->get('doctrine');
+ }
+
+ /**
+ * Get a user from the Security Token Storage.
+ *
+ * @return mixed
+ *
+ * @throws \LogicException If SecurityBundle is not available
+ *
+ * @see TokenInterface::getUser()
+ */
+ protected function getUser()
+ {
+ if (!$this->container->has('security.token_storage')) {
+ throw new \LogicException('The SecurityBundle is not registered in your application.');
+ }
+
+ if (null === $token = $this->container->get('security.token_storage')->getToken()) {
+ return;
+ }
+
+ if (!is_object($user = $token->getUser())) {
+ // e.g. anonymous authentication
+ return;
+ }
+
+ return $user;
+ }
+
+ /**
+ * Checks the validity of a CSRF token.
+ *
+ * @param string $id The id used when generating the token
+ * @param string $token The actual token sent with the request that should be validated
+ *
+ * @return bool
+ */
+ protected function isCsrfTokenValid($id, $token)
+ {
+ if (!$this->container->has('security.csrf.token_manager')) {
+ throw new \LogicException('CSRF protection is not enabled in your application.');
+ }
+
+ return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token));
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php
index d222bc7ea37a2..1d4c44c6b4714 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php
@@ -36,8 +36,13 @@ class TemplateController implements ContainerAwareInterface
*/
public function templateAction($template, $maxAge = null, $sharedAge = null, $private = null)
{
- /** @var $response \Symfony\Component\HttpFoundation\Response */
- $response = $this->container->get('templating')->renderResponse($template);
+ if ($this->container->has('templating')) {
+ $response = $this->container->get('templating')->renderResponse($template);
+ } elseif ($this->container->has('twig')) {
+ $response = new Response($this->container->get('twig')->render($template));
+ } else {
+ throw new \LogicException('You can not use the TemplateController if the Templating Component or the Twig Bundle are not available.');
+ }
if ($maxAge) {
$response->setMaxAge($maxAge);
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php
new file mode 100644
index 0000000000000..508899379f691
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @internal
+ */
+class AddAnnotationsCachedReaderPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ // "annotations.cached_reader" is wired late so that any passes using
+ // "annotation_reader" at build time don't get any cache
+ if ($container->hasDefinition('annotations.cached_reader')) {
+ $reader = $container->getDefinition('annotations.cached_reader');
+ $tags = $reader->getTags();
+
+ if (isset($tags['annotations.cached_reader'][0]['provider'])) {
+ if ($container->hasAlias($provider = $tags['annotations.cached_reader'][0]['provider'])) {
+ $provider = (string) $container->getAlias($provider);
+ }
+ $container->set('annotations.cached_reader', null);
+ $container->setDefinition('annotations.cached_reader', $reader->replaceArgument(1, new Reference($provider)));
+ }
+ }
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php
index 27b9b465c913c..88cfffd04f123 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php
@@ -32,7 +32,7 @@ public function process(ContainerBuilder $container)
}
$clearers = array();
- foreach ($container->findTaggedServiceIds('kernel.cache_clearer') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('kernel.cache_clearer', true) as $id => $attributes) {
$clearers[] = new Reference($id);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php
index 37d7810ecac7a..d423648d05b1a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php
@@ -11,41 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+@trigger_error(sprintf('%s is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass instead.', AddConsoleCommandPass::class), E_USER_DEPRECATED);
+
+use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass as BaseAddConsoleCommandPass;
/**
- * AddConsoleCommandPass.
+ * Registers console commands.
*
* @author Grégoire Pineau
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass instead.
*/
-class AddConsoleCommandPass implements CompilerPassInterface
+class AddConsoleCommandPass extends BaseAddConsoleCommandPass
{
- public function process(ContainerBuilder $container)
- {
- $commandServices = $container->findTaggedServiceIds('console.command');
- $serviceIds = array();
-
- foreach ($commandServices as $id => $tags) {
- $definition = $container->getDefinition($id);
-
- if ($definition->isAbstract()) {
- throw new InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must not be abstract.', $id));
- }
-
- $class = $container->getParameterBag()->resolveValue($definition->getClass());
- if (!is_subclass_of($class, 'Symfony\\Component\\Console\\Command\\Command')) {
- if (!class_exists($class, false)) {
- throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
- }
-
- throw new InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "Symfony\\Component\\Console\\Command\\Command".', $id));
- }
- $container->setAlias($serviceId = 'console.command.'.strtolower(str_replace('\\', '_', $class)), $id);
- $serviceIds[] = $definition->isPublic() ? $id : $serviceId;
- }
-
- $container->setParameter('console.command.ids', $serviceIds);
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
index 497ea08a4bf4e..3b89fa2651a80 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
@@ -11,37 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass as BaseAddConstraintValidatorsPass;
-class AddConstraintValidatorsPass implements CompilerPassInterface
-{
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition('validator.validator_factory')) {
- return;
- }
-
- $validators = array();
- foreach ($container->findTaggedServiceIds('validator.constraint_validator') as $id => $attributes) {
- if (isset($attributes[0]['alias'])) {
- $validators[$attributes[0]['alias']] = $id;
- }
-
- $definition = $container->getDefinition($id);
-
- if (!$definition->isPublic()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must be public as it can be lazy-loaded.', $id));
- }
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddConstraintValidatorsPass::class, BaseAddConstraintValidatorsPass::class), E_USER_DEPRECATED);
- if ($definition->isAbstract()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id));
- }
-
- $validators[$definition->getClass()] = $id;
- }
-
- $container->getDefinition('validator.validator_factory')->replaceArgument(1, $validators);
- }
+/**
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddConstraintValidatorsPass} instead
+ */
+class AddConstraintValidatorsPass extends BaseAddConstraintValidatorsPass
+{
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
index 6510d02c83063..d4103d8dff1a1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
@@ -30,7 +30,7 @@ public function process(ContainerBuilder $container)
// routing
if ($container->has('router')) {
$definition = $container->findDefinition('router');
- foreach ($container->findTaggedServiceIds('routing.expression_language_provider') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('routing.expression_language_provider', true) as $id => $attributes) {
$definition->addMethodCall('addExpressionLanguageProvider', array(new Reference($id)));
}
}
@@ -38,7 +38,7 @@ public function process(ContainerBuilder $container)
// security
if ($container->has('security.access.expression_voter')) {
$definition = $container->findDefinition('security.access.expression_voter');
- foreach ($container->findTaggedServiceIds('security.expression_language_provider') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('security.expression_language_provider', true) as $id => $attributes) {
$definition->addMethodCall('addExpressionLanguageProvider', array(new Reference($id)));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php
index 6f58fc21bebf1..d71d87c1faad4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php
@@ -11,25 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass as BaseAddValidatorsInitializerPass;
-class AddValidatorInitializersPass implements CompilerPassInterface
-{
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition('validator.builder')) {
- return;
- }
-
- $validatorBuilder = $container->getDefinition('validator.builder');
-
- $initializers = array();
- foreach ($container->findTaggedServiceIds('validator.initializer') as $id => $attributes) {
- $initializers[] = new Reference($id);
- }
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddValidatorInitializersPass::class, BaseAddValidatorsInitializerPass::class), E_USER_DEPRECATED);
- $validatorBuilder->addMethodCall('addObjectInitializers', array($initializers));
- }
+/**
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddValidatorInitializersPass} instead
+ */
+class AddValidatorInitializersPass extends BaseAddValidatorsInitializerPass
+{
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php
new file mode 100644
index 0000000000000..3d1908bf9bc92
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\Cache\Adapter\TraceableAdapter;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Inject a data collector to all the cache services to be able to get detailed statistics.
+ *
+ * @author Tobias Nyholm
+ */
+class CacheCollectorPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition('data_collector.cache')) {
+ return;
+ }
+
+ $collectorDefinition = $container->getDefinition('data_collector.cache');
+ foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
+ if ($container->getDefinition($id)->isAbstract()) {
+ continue;
+ }
+
+ $container->register($id.'.recorder', TraceableAdapter::class)
+ ->setDecoratedService($id)
+ ->addArgument(new Reference($id.'.recorder.inner'))
+ ->setPublic(false);
+
+ // Tell the collector to add the new instance
+ $collectorDefinition->addMethodCall('addInstance', array($id, new Reference($id)));
+ }
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
index c859a6ba900a4..882f9b2dccf67 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
@@ -27,31 +27,43 @@ final class CachePoolClearerPass implements CompilerPassInterface
public function process(ContainerBuilder $container)
{
$container->getParameterBag()->remove('cache.prefix.seed');
+ $poolsByClearer = array();
+ $pools = array();
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
+ $pools[$id] = new Reference($id);
foreach (array_reverse($attributes) as $attr) {
if (isset($attr['clearer'])) {
- $clearer = $container->getDefinition($attr['clearer']);
- $clearer->addMethodCall('addPool', array(new Reference($id)));
+ $poolsByClearer[$attr['clearer']][$id] = $pools[$id];
}
- if (array_key_exists('clearer', $attr)) {
+ if (!empty($attr['unlazy'])) {
+ $container->getDefinition($id)->setLazy(false);
+ }
+ if (array_key_exists('clearer', $attr) || array_key_exists('unlazy', $attr)) {
break;
}
}
}
+ $container->getDefinition('cache.global_clearer')->addArgument($pools);
+
+ foreach ($poolsByClearer as $clearer => $pools) {
+ $clearer = $container->getDefinition($clearer);
+ $clearer->addArgument($pools);
+ }
+
if (!$container->has('cache.annotations')) {
return;
}
$factory = array(AbstractAdapter::class, 'createSystemCache');
- $annotationsPool = $container->getDefinition('cache.annotations');
+ $annotationsPool = $container->findDefinition('cache.annotations');
if ($factory !== $annotationsPool->getFactory() || 4 !== count($annotationsPool->getArguments())) {
return;
}
if ($container->has('monolog.logger.cache')) {
$annotationsPool->addArgument(new Reference('monolog.logger.cache'));
} elseif ($container->has('cache.system')) {
- $systemPool = $container->getDefinition('cache.system');
+ $systemPool = $container->findDefinition('cache.system');
if ($factory === $systemPool->getFactory() && 5 <= count($systemArgs = $systemPool->getArguments())) {
$annotationsPool->addArgument($systemArgs[4]);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
index 593b7782c66b0..e4a86dc6ef249 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -11,11 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\Cache\Adapter\RedisAdapter;
+use Symfony\Component\Cache\Adapter\AbstractAdapter;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -34,9 +34,8 @@ public function process(ContainerBuilder $container)
} else {
$seed = '_'.$container->getParameter('kernel.root_dir');
}
- $seed .= '.'.$container->getParameter('kernel.name').'.'.$container->getParameter('kernel.environment').'.'.$container->getParameter('kernel.debug');
+ $seed .= '.'.$container->getParameter('kernel.name').'.'.$container->getParameter('kernel.environment');
- $aliases = $container->getAliases();
$attributes = array(
'provider',
'namespace',
@@ -47,8 +46,10 @@ public function process(ContainerBuilder $container)
if ($pool->isAbstract()) {
continue;
}
- while ($adapter instanceof DefinitionDecorator) {
+ $isLazy = $pool->isLazy();
+ while ($adapter instanceof ChildDefinition) {
$adapter = $container->findDefinition($adapter->getParent());
+ $isLazy = $isLazy || $adapter->isLazy();
if ($t = $adapter->getTag('cache.pool')) {
$tags[0] += $t[0];
}
@@ -57,9 +58,9 @@ public function process(ContainerBuilder $container)
$tags[0]['namespace'] = $this->getNamespace($seed, $id);
}
if (isset($tags[0]['clearer'])) {
- $clearer = strtolower($tags[0]['clearer']);
- while (isset($aliases[$clearer])) {
- $clearer = (string) $aliases[$clearer];
+ $clearer = $tags[0]['clearer'];
+ while ($container->hasAlias($clearer)) {
+ $clearer = (string) $container->getAlias($clearer);
}
} else {
$clearer = null;
@@ -80,8 +81,16 @@ public function process(ContainerBuilder $container)
throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0]))));
}
+ $attr = array();
if (null !== $clearer) {
- $pool->addTag('cache.pool', array('clearer' => $clearer));
+ $attr['clearer'] = $clearer;
+ }
+ if (!$isLazy) {
+ $pool->setLazy(true);
+ $attr['unlazy'] = true;
+ }
+ if ($attr) {
+ $pool->addTag('cache.pool', $attr);
}
}
}
@@ -96,13 +105,15 @@ private function getNamespace($seed, $id)
*/
public static function getServiceProvider(ContainerBuilder $container, $name)
{
- if (0 === strpos($name, 'redis://')) {
+ $container->resolveEnvPlaceholders($name, null, $usedEnvs);
+
+ if ($usedEnvs || preg_match('#^[a-z]++://#', $name)) {
$dsn = $name;
if (!$container->hasDefinition($name = md5($dsn))) {
- $definition = new Definition(\Redis::class);
+ $definition = new Definition(AbstractAdapter::class);
$definition->setPublic(false);
- $definition->setFactory(array(RedisAdapter::class, 'createConnection'));
+ $definition->setFactory(array(AbstractAdapter::class, 'createConnection'));
$definition->setArguments(array($dsn));
$container->setDefinition($name, $definition);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php
index f152ce8c509cb..714d01d01d5e5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php
@@ -11,12 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', CompilerDebugDumpPass::class), E_USER_DEPRECATED);
+
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
+/**
+ * @deprecated since version 3.3, to be removed in 4.0.
+ */
class CompilerDebugDumpPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php
index d73e941f427ba..7fcea3b0e555d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php
@@ -11,28 +11,18 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\Config\DependencyInjection\ConfigCachePass as BaseConfigCachePass;
+
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Config\DependencyInjection\ConfigCachePass instead.', ConfigCachePass::class), E_USER_DEPRECATED);
/**
* Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority.
*
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseConfigCachePass} instead.
+ *
* @author Matthias Pigulla
* @author Benjamin Klotz
*/
-class ConfigCachePass implements CompilerPassInterface
+class ConfigCachePass extends BaseConfigCachePass
{
- use PriorityTaggedServiceTrait;
-
- public function process(ContainerBuilder $container)
- {
- $resourceCheckers = $this->findAndSortTaggedServices('config_cache.resource_checker', $container);
-
- if (empty($resourceCheckers)) {
- return;
- }
-
- $container->getDefinition('config_cache_factory')->replaceArgument(0, $resourceCheckers);
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php
index e087e691440f9..3f2baf6871c13 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php
@@ -11,27 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass as BaseControllerArgumentValueResolverPass;
+
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', ControllerArgumentValueResolverPass::class, BaseControllerArgumentValueResolverPass::class), E_USER_DEPRECATED);
/**
* Gathers and configures the argument value resolvers.
*
* @author Iltar van der Berg
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseControllerArgumentValueResolverPass}
*/
-class ControllerArgumentValueResolverPass implements CompilerPassInterface
+class ControllerArgumentValueResolverPass extends BaseControllerArgumentValueResolverPass
{
- use PriorityTaggedServiceTrait;
-
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition('argument_resolver')) {
- return;
- }
-
- $definition = $container->getDefinition('argument_resolver');
- $argumentResolvers = $this->findAndSortTaggedServices('controller.argument_value_resolver', $container);
- $definition->replaceArgument(1, $argumentResolvers);
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php
new file mode 100644
index 0000000000000..ee2bbb6521b17
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * @author Christian Flothmann
+ */
+class DataCollectorTranslatorPass implements CompilerPassInterface
+{
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->has('translator')) {
+ return;
+ }
+
+ $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass());
+
+ if (!is_subclass_of($translatorClass, 'Symfony\Component\Translation\TranslatorBagInterface')) {
+ $container->removeDefinition('translator.data_collector');
+ $container->removeDefinition('data_collector.translation');
+ }
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
index c248a079df2a9..fdbfd4297b225 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
@@ -11,6 +11,8 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Form\DependencyInjection\FormPass instead.', FormPass::class), E_USER_DEPRECATED);
+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@@ -21,6 +23,8 @@
* arguments of the "form.extension" service.
*
* @author Bernhard Schussek
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use FormPass in the Form component instead.
*/
class FormPass implements CompilerPassInterface
{
@@ -40,7 +44,7 @@ public function process(ContainerBuilder $container)
foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) {
$serviceDefinition = $container->getDefinition($serviceId);
if (!$serviceDefinition->isPublic()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must be public as form types are lazy-loaded.', $serviceId));
+ $serviceDefinition->setPublic(true);
}
// Support type access by FQCN
@@ -55,7 +59,7 @@ public function process(ContainerBuilder $container)
$serviceId = (string) $reference;
$serviceDefinition = $container->getDefinition($serviceId);
if (!$serviceDefinition->isPublic()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type extensions are lazy-loaded.', $serviceId));
+ $serviceDefinition->setPublic(true);
}
$tag = $serviceDefinition->getTag('form.type_extension');
@@ -75,7 +79,7 @@ public function process(ContainerBuilder $container)
foreach ($guessers as $serviceId) {
$serviceDefinition = $container->getDefinition($serviceId);
if (!$serviceDefinition->isPublic()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type guessers are lazy-loaded.', $serviceId));
+ $serviceDefinition->setPublic(true);
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php
index 74d586bf3b852..7d47dd2f9b132 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php
@@ -13,7 +13,10 @@
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\Translation\TranslatorInterface;
+use Symfony\Component\Translation\TranslatorBagInterface;
/**
* @author Abdellatif Ait boudad
@@ -31,7 +34,10 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition((string) $translatorAlias);
$class = $container->getParameterBag()->resolveValue($definition->getClass());
- if (is_subclass_of($class, 'Symfony\Component\Translation\TranslatorInterface') && is_subclass_of($class, 'Symfony\Component\Translation\TranslatorBagInterface')) {
+ if (!$r = $container->getReflectionClass($class)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
+ }
+ if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) {
$container->getDefinition('translator.logging')->setDecoratedService('translator');
$container->getDefinition('translation.warmer')->replaceArgument(0, new Reference('translator.logging.inner'));
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php
index 046407351ceeb..28cc83dfd3004 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php
@@ -33,7 +33,7 @@ public function process(ContainerBuilder $container)
$collectors = new \SplPriorityQueue();
$order = PHP_INT_MAX;
- foreach ($container->findTaggedServiceIds('data_collector') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('data_collector', true) as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$template = null;
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php
index f05445f1a6276..3c73f9bf49507 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php
@@ -11,40 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass instead.', PropertyInfoPass::class), E_USER_DEPRECATED);
+
+use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass as BasePropertyInfoPass;
/**
* Adds extractors to the property_info service.
*
* @author Kévin Dunglas
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BasePropertyInfoPass instead}.
*/
-class PropertyInfoPass implements CompilerPassInterface
+class PropertyInfoPass extends BasePropertyInfoPass
{
- use PriorityTaggedServiceTrait;
-
- /**
- * {@inheritdoc}
- */
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition('property_info')) {
- return;
- }
-
- $definition = $container->getDefinition('property_info');
-
- $listExtractors = $this->findAndSortTaggedServices('property_info.list_extractor', $container);
- $definition->replaceArgument(0, $listExtractors);
-
- $typeExtractors = $this->findAndSortTaggedServices('property_info.type_extractor', $container);
- $definition->replaceArgument(1, $typeExtractors);
-
- $descriptionExtractors = $this->findAndSortTaggedServices('property_info.description_extractor', $container);
- $definition->replaceArgument(2, $descriptionExtractors);
-
- $accessExtractors = $this->findAndSortTaggedServices('property_info.access_extractor', $container);
- $definition->replaceArgument(3, $accessExtractors);
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php
index 6ff7c124cdac0..bac782115b557 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php
@@ -11,27 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass as BaseRoutingResolverPass;
+
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', RoutingResolverPass::class, BaseRoutingResolverPass::class), E_USER_DEPRECATED);
/**
* Adds tagged routing.loader services to routing.resolver service.
*
* @author Fabien Potencier
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseRoutingResolverPass}
*/
-class RoutingResolverPass implements CompilerPassInterface
+class RoutingResolverPass extends BaseRoutingResolverPass
{
- public function process(ContainerBuilder $container)
- {
- if (false === $container->hasDefinition('routing.resolver')) {
- return;
- }
-
- $definition = $container->getDefinition('routing.resolver');
-
- foreach ($container->findTaggedServiceIds('routing.loader') as $id => $attributes) {
- $definition->addMethodCall('addLoader', array(new Reference($id)));
- }
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php
index d3d3019998c84..d30e8eba43a17 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php
@@ -11,40 +11,18 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Serializer\DependencyInjection\SerializerPass instead.', SerializerPass::class), E_USER_DEPRECATED);
+
+use Symfony\Component\Serializer\DependencyInjection\SerializerPass as BaseSerializerPass;
/**
* Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
* encoders and normalizers to the Serializer service.
*
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseSerializerPass} instead.
+ *
* @author Javier Lopez
*/
-class SerializerPass implements CompilerPassInterface
+class SerializerPass extends BaseSerializerPass
{
- use PriorityTaggedServiceTrait;
-
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition('serializer')) {
- return;
- }
-
- // Looks for all the services tagged "serializer.normalizer" and adds them to the Serializer service
- $normalizers = $this->findAndSortTaggedServices('serializer.normalizer', $container);
-
- if (empty($normalizers)) {
- throw new RuntimeException('You must tag at least one service as "serializer.normalizer" to use the Serializer service');
- }
- $container->getDefinition('serializer')->replaceArgument(0, $normalizers);
-
- // Looks for all the services tagged "serializer.encoders" and adds them to the Serializer service
- $encoders = $this->findAndSortTaggedServices('serializer.encoder', $container);
- if (empty($encoders)) {
- throw new RuntimeException('You must tag at least one service as "serializer.encoder" to use the Serializer service');
- }
- $container->getDefinition('serializer')->replaceArgument(1, $encoders);
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php
index 4ef67a42b6fe6..8e2e4d0dbfb34 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php
@@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundleEngineInterface;
+use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface;
@@ -25,13 +26,13 @@ public function process(ContainerBuilder $container)
}
if ($container->hasAlias('templating')) {
- $definition = $container->findDefinition('templating');
- $definition->setAutowiringTypes(array(ComponentEngineInterface::class, FrameworkBundleEngineInterface::class));
+ $container->setAlias(ComponentEngineInterface::class, new Alias('templating', false));
+ $container->setAlias(FrameworkBundleEngineInterface::class, new Alias('templating', false));
}
if ($container->hasDefinition('templating.engine.php')) {
$helpers = array();
- foreach ($container->findTaggedServiceIds('templating.helper') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('templating.helper', true) as $id => $attributes) {
if (isset($attributes[0]['alias'])) {
$helpers[$attributes[0]['alias']] = $id;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php
index f7c09748b4f7e..541b06b31e254 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php
@@ -28,7 +28,7 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition('translation.writer');
- foreach ($container->findTaggedServiceIds('translation.dumper') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('translation.dumper', true) as $id => $attributes) {
$definition->addMethodCall('addDumper', array($attributes[0]['alias'], new Reference($id)));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php
index fc8a66d24fa06..4dc8d3985ce68 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php
@@ -29,7 +29,7 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition('translation.extractor');
- foreach ($container->findTaggedServiceIds('translation.extractor') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) {
if (!isset($attributes[0]['alias'])) {
throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php
index 4e450166afa44..29e251f274339 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php
@@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
class TranslatorPass implements CompilerPassInterface
{
@@ -24,7 +25,9 @@ public function process(ContainerBuilder $container)
}
$loaders = array();
- foreach ($container->findTaggedServiceIds('translation.loader') as $id => $attributes) {
+ $loaderRefs = array();
+ foreach ($container->findTaggedServiceIds('translation.loader', true) as $id => $attributes) {
+ $loaderRefs[$id] = new Reference($id);
$loaders[$id][] = $attributes[0]['alias'];
if (isset($attributes[0]['legacy-alias'])) {
$loaders[$id][] = $attributes[0]['legacy-alias'];
@@ -35,11 +38,15 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition('translation.loader');
foreach ($loaders as $id => $formats) {
foreach ($formats as $format) {
- $definition->addMethodCall('addLoader', array($format, new Reference($id)));
+ $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
}
}
}
- $container->findDefinition('translator.default')->replaceArgument(2, $loaders);
+ $container
+ ->findDefinition('translator.default')
+ ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
+ ->replaceArgument(3, $loaders)
+ ;
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
index ed852fd041942..ffc19c49dfeff 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
@@ -23,6 +23,9 @@ class UnusedTagsPass implements CompilerPassInterface
{
private $whitelist = array(
'console.command',
+ 'container.service_locator',
+ 'container.service_subscriber',
+ 'controller.service_arguments',
'config_cache.resource_checker',
'data_collector',
'form.type',
@@ -53,8 +56,6 @@ class UnusedTagsPass implements CompilerPassInterface
public function process(ContainerBuilder $container)
{
- $compiler = $container->getCompiler();
- $formatter = $compiler->getLoggingFormatter();
$tags = array_unique(array_merge($container->findTags(), $this->whitelist));
foreach ($container->findUnusedTags() as $tag) {
@@ -81,7 +82,7 @@ public function process(ContainerBuilder $container)
$message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates));
}
- $compiler->addLogMessage($formatter->format($this, $message));
+ $container->log($this, $message);
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php
index a2f695992926d..6599f1f1a0300 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php
@@ -11,54 +11,15 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
-use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface;
-use Symfony\Component\Workflow\Validator\StateMachineValidator;
-use Symfony\Component\Workflow\Validator\WorkflowValidator;
+use Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass as BaseValidateWorkflowsPass;
+
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', ValidateWorkflowsPass::class, BaseValidateWorkflowsPass::class), E_USER_DEPRECATED);
/**
* @author Tobias Nyholm
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseValidateWorkflowsPass} instead
*/
-class ValidateWorkflowsPass implements CompilerPassInterface
+class ValidateWorkflowsPass extends BaseValidateWorkflowsPass
{
- public function process(ContainerBuilder $container)
- {
- $taggedServices = $container->findTaggedServiceIds('workflow.definition');
- foreach ($taggedServices as $id => $tags) {
- $definition = $container->get($id);
- foreach ($tags as $tag) {
- if (!array_key_exists('name', $tag)) {
- throw new RuntimeException(sprintf('The "name" for the tag "workflow.definition" of service "%s" must be set.', $id));
- }
- if (!array_key_exists('type', $tag)) {
- throw new RuntimeException(sprintf('The "type" for the tag "workflow.definition" of service "%s" must be set.', $id));
- }
- if (!array_key_exists('marking_store', $tag)) {
- throw new RuntimeException(sprintf('The "marking_store" for the tag "workflow.definition" of service "%s" must be set.', $id));
- }
-
- $this->createValidator($tag)->validate($definition, $tag['name']);
- }
- }
- }
-
- /**
- * @param array $tag
- *
- * @return DefinitionValidatorInterface
- */
- private function createValidator($tag)
- {
- if ('state_machine' === $tag['type']) {
- return new StateMachineValidator();
- }
-
- if ('single_state' === $tag['marking_store']) {
- return new WorkflowValidator(true);
- }
-
- return new WorkflowValidator();
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 5c6208e6e46f2..87d722b91e4d6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -11,9 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
+use Doctrine\Common\Annotations\Annotation;
+use Symfony\Bundle\FullStack;
+use Symfony\Component\Asset\Package;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
+use Symfony\Component\Form\Form;
+use Symfony\Component\Serializer\Serializer;
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Validator\Validation;
+use Symfony\Component\WebLink\HttpHeaderSerializer;
/**
* FrameworkExtension configuration structure.
@@ -57,34 +65,10 @@ public function getConfigTreeBuilder()
->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead")
->defaultTrue()
->end()
- ->arrayNode('trusted_proxies')
+ ->arrayNode('trusted_proxies') // @deprecated in version 3.3, to be removed in 4.0
->beforeNormalization()
- ->ifTrue(function ($v) { return !is_array($v) && null !== $v; })
- ->then(function ($v) { return is_bool($v) ? array() : preg_split('/\s*,\s*/', $v); })
- ->end()
- ->prototype('scalar')
- ->validate()
- ->ifTrue(function ($v) {
- if (empty($v)) {
- return false;
- }
-
- if (false !== strpos($v, '/')) {
- if ('0.0.0.0/0' === $v) {
- return false;
- }
-
- list($v, $mask) = explode('/', $v, 2);
-
- if (strcmp($mask, (int) $mask) || $mask < 1 || $mask > (false !== strpos($v, ':') ? 128 : 32)) {
- return true;
- }
- }
-
- return !filter_var($v, FILTER_VALIDATE_IP);
- })
- ->thenInvalid('Invalid proxy IP "%s"')
- ->end()
+ ->always()
+ ->thenInvalid('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.')
->end()
->end()
->scalarNode('ide')->defaultNull()->end()
@@ -117,6 +101,7 @@ public function getConfigTreeBuilder()
$this->addPropertyInfoSection($rootNode);
$this->addCacheSection($rootNode);
$this->addPhpErrorsSection($rootNode);
+ $this->addWebLinkSection($rootNode);
return $treeBuilder;
}
@@ -138,7 +123,7 @@ private function addFormSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('form')
->info('form configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && class_exists(Form::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
->arrayNode('csrf_protection')
->treatFalseLike(array('enabled' => false))
@@ -240,9 +225,11 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->fixXmlConfig('place')
->fixXmlConfig('transition')
->children()
+ ->arrayNode('audit_trail')
+ ->canBeEnabled()
+ ->end()
->enumNode('type')
->values(array('workflow', 'state_machine'))
- ->defaultValue('workflow')
->end()
->arrayNode('marking_store')
->fixXmlConfig('argument')
@@ -268,12 +255,11 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->thenInvalid('"type" and "service" cannot be used together.')
->end()
->validate()
- ->ifTrue(function ($v) { return isset($v['arguments']) && isset($v['service']); })
+ ->ifTrue(function ($v) { return !empty($v['arguments']) && isset($v['service']); })
->thenInvalid('"arguments" and "service" cannot be used together.')
->end()
->end()
->arrayNode('supports')
- ->isRequired()
->beforeNormalization()
->ifString()
->then(function ($v) { return array($v); })
@@ -286,7 +272,12 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->end()
->end()
->end()
- ->scalarNode('initial_place')->defaultNull()->end()
+ ->scalarNode('support_strategy')
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('initial_place')
+ ->defaultNull()
+ ->end()
->arrayNode('places')
->isRequired()
->requiresAtLeastOneElement()
@@ -295,11 +286,38 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->end()
->end()
->arrayNode('transitions')
- ->useAttributeAsKey('name')
+ ->beforeNormalization()
+ ->always()
+ ->then(function ($transitions) {
+ // It's an indexed array, we let the validation occurs
+ if (isset($transitions[0])) {
+ return $transitions;
+ }
+
+ foreach ($transitions as $name => $transition) {
+ if (array_key_exists('name', $transition)) {
+ continue;
+ }
+ $transition['name'] = $name;
+ $transitions[$name] = $transition;
+ }
+
+ return $transitions;
+ })
+ ->end()
->isRequired()
->requiresAtLeastOneElement()
->prototype('array')
->children()
+ ->scalarNode('name')
+ ->isRequired()
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('guard')
+ ->cannotBeEmpty()
+ ->info('An expression to block the transition')
+ ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')
+ ->end()
->arrayNode('from')
->beforeNormalization()
->ifString()
@@ -324,6 +342,18 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->end()
->end()
->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return $v['supports'] && isset($v['support_strategy']);
+ })
+ ->thenInvalid('"supports" and "support_strategy" cannot be used together.')
+ ->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return !$v['supports'] && !isset($v['support_strategy']);
+ })
+ ->thenInvalid('"supports" or "support_strategy" should be configured.')
+ ->end()
->end()
->end()
->end()
@@ -483,12 +513,13 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('assets')
->info('assets configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && class_exists(Package::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->fixXmlConfig('base_url')
->children()
->scalarNode('version_strategy')->defaultNull()->end()
->scalarNode('version')->defaultNull()->end()
->scalarNode('version_format')->defaultValue('%%s?%%s')->end()
+ ->scalarNode('json_manifest_path')->defaultNull()->end()
->scalarNode('base_path')->defaultValue('')->end()
->arrayNode('base_urls')
->requiresAtLeastOneElement()
@@ -505,6 +536,18 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
})
->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".')
->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return isset($v['version_strategy']) && isset($v['json_manifest_path']);
+ })
+ ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".')
+ ->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return isset($v['version']) && isset($v['json_manifest_path']);
+ })
+ ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".')
+ ->end()
->fixXmlConfig('package')
->children()
->arrayNode('packages')
@@ -520,6 +563,7 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
->end()
->end()
->scalarNode('version_format')->defaultNull()->end()
+ ->scalarNode('json_manifest_path')->defaultNull()->end()
->scalarNode('base_path')->defaultValue('')->end()
->arrayNode('base_urls')
->requiresAtLeastOneElement()
@@ -536,6 +580,18 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
})
->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.')
->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return isset($v['version_strategy']) && isset($v['json_manifest_path']);
+ })
+ ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.')
+ ->end()
+ ->validate()
+ ->ifTrue(function ($v) {
+ return isset($v['version']) && isset($v['json_manifest_path']);
+ })
+ ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.')
+ ->end()
->end()
->end()
->end()
@@ -550,7 +606,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('translator')
->info('translator configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && class_exists(Translator::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->fixXmlConfig('fallback')
->fixXmlConfig('path')
->children()
@@ -575,10 +631,10 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('validation')
->info('validation configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
->scalarNode('cache')->end()
- ->booleanNode('enable_annotations')->defaultFalse()->end()
+ ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end()
->arrayNode('static_method')
->defaultValue(array('loadValidatorMetadata'))
->prototype('scalar')->end()
@@ -590,6 +646,15 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
->end()
->scalarNode('translation_domain')->defaultValue('validators')->end()
->booleanNode('strict_email')->defaultFalse()->end()
+ ->arrayNode('mapping')
+ ->addDefaultsIfNotSet()
+ ->fixXmlConfig('path')
+ ->children()
+ ->arrayNode('paths')
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
+ ->end()
->end()
->end()
->end()
@@ -602,7 +667,7 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('annotations')
->info('annotation configuration')
- ->canBeDisabled()
+ ->{class_exists(Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
->scalarNode('cache')->defaultValue('php_array')->end()
->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end()
@@ -619,11 +684,21 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('serializer')
->info('serializer configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && class_exists(Serializer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
- ->booleanNode('enable_annotations')->defaultFalse()->end()
+ ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end()
->scalarNode('cache')->end()
->scalarNode('name_converter')->end()
+ ->scalarNode('circular_reference_handler')->end()
+ ->arrayNode('mapping')
+ ->addDefaultsIfNotSet()
+ ->fixXmlConfig('path')
+ ->children()
+ ->arrayNode('paths')
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
+ ->end()
->end()
->end()
->end()
@@ -683,6 +758,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode)
->scalarNode('default_doctrine_provider')->end()
->scalarNode('default_psr6_provider')->end()
->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()
+ ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end()
->arrayNode('pools')
->useAttributeAsKey('name')
->prototype('array')
@@ -730,4 +806,16 @@ private function addPhpErrorsSection(ArrayNodeDefinition $rootNode)
->end()
;
}
+
+ private function addWebLinkSection(ArrayNodeDefinition $rootNode)
+ {
+ $rootNode
+ ->children()
+ ->arrayNode('web_link')
+ ->info('web links configuration')
+ ->{!class_exists(FullStack::class) && class_exists(HttpHeaderSerializer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
+ ->end()
+ ->end()
+ ;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 61a7d7a9170d3..c65c1f8e740be 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -13,29 +13,51 @@
use Doctrine\Common\Annotations\Reader;
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Config\ResourceCheckerInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Exception\LogicException;
-use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
-use Symfony\Component\Config\Resource\FileResource;
-use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Finder\Finder;
+use Symfony\Component\Form\FormTypeGuesserInterface;
+use Symfony\Component\Form\FormTypeInterface;
+use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
+use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
+use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
-use Symfony\Component\Config\FileLocator;
use Symfony\Component\PropertyAccess\PropertyAccessor;
-use Symfony\Component\Serializer\Encoder\YamlEncoder;
+use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
+use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
+use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
+use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Serializer\Encoder\CsvEncoder;
+use Symfony\Component\Serializer\Encoder\EncoderInterface;
+use Symfony\Component\Serializer\Encoder\YamlEncoder;
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
+use Symfony\Component\Validator\ConstraintValidatorInterface;
+use Symfony\Component\Validator\ObjectInitializerInterface;
+use Symfony\Component\WebLink\HttpHeaderSerializer;
use Symfony\Component\Workflow;
-use Symfony\Component\Yaml\Yaml;
/**
* FrameworkExtension.
@@ -71,8 +93,20 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('web.xml');
$loader->load('services.xml');
+
+ if (PHP_VERSION_ID < 70000) {
+ $definition = $container->getDefinition('kernel.class_cache.cache_warmer');
+ $definition->addTag('kernel.cache_warmer');
+ // Ignore deprecation for PHP versions below 7.0
+ $definition->setDeprecated(false);
+ }
+
$loader->load('fragment_renderer.xml');
+ if (class_exists(Application::class)) {
+ $loader->load('console.xml');
+ }
+
// Property access is used by both the Form and the Validator component
$loader->load('property_access.xml');
@@ -83,16 +117,25 @@ public function load(array $configs, ContainerBuilder $container)
$config = $this->processConfiguration($configuration, $configs);
$this->annotationsConfigEnabled = $this->isConfigEnabled($container, $config['annotations']);
+ $this->translationConfigEnabled = $this->isConfigEnabled($container, $config['translator']);
// A translator must always be registered (as support is included by
- // default in the Form component). If disabled, an identity translator
- // will be used and everything will still work as expected.
- if (class_exists('Symfony\Component\Translation\Translator') || $this->isConfigEnabled($container, $config['form'])) {
- if (!class_exists('Symfony\Component\Translation\Translator')) {
+ // default in the Form and Validator component). If disabled, an identity
+ // translator will be used and everything will still work as expected.
+ if ($this->isConfigEnabled($container, $config['translator']) || $this->isConfigEnabled($container, $config['form']) || $this->isConfigEnabled($container, $config['validation'])) {
+ if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['translator'])) {
+ throw new LogicException('Translation support cannot be enabled as the Translation component is not installed.');
+ }
+
+ if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['form'])) {
throw new LogicException('Form support cannot be enabled as the Translation component is not installed.');
}
- $loader->load('translation.xml');
+ if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['validation'])) {
+ throw new LogicException('Validation support cannot be enabled as the Translation component is not installed.');
+ }
+
+ $loader->load('identity_translator.xml');
}
if (isset($config['secret'])) {
@@ -101,7 +144,6 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('kernel.http_method_override', $config['http_method_override']);
$container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
- $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
$container->setParameter('kernel.default_locale', $config['default_locale']);
if (!$container->hasParameter('debug.file_link_format')) {
@@ -111,7 +153,7 @@ public function load(array $configs, ContainerBuilder $container)
'macvim' => 'mvim://open?url=file://%%f&line=%%l',
'emacs' => 'emacs://open?url=file://%%f&line=%%l',
'sublime' => 'subl://open?url=file://%%f&line=%%l',
- 'phpstorm' => 'phpstorm://open?url=file://%%f&line=%%l',
+ 'phpstorm' => 'phpstorm://open?file=%%f&line=%%l',
);
$ide = $config['ide'];
@@ -165,7 +207,7 @@ public function load(array $configs, ContainerBuilder $container)
$this->registerEsiConfiguration($config['esi'], $container, $loader);
$this->registerSsiConfiguration($config['ssi'], $container, $loader);
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
- $this->registerTranslatorConfiguration($config['translator'], $container);
+ $this->registerTranslatorConfiguration($config['translator'], $container, $loader);
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
$this->registerCacheConfiguration($config['cache'], $container);
$this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
@@ -186,6 +228,14 @@ public function load(array $configs, ContainerBuilder $container)
$this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader);
}
+ if ($this->isConfigEnabled($container, $config['web_link'])) {
+ if (!class_exists(HttpHeaderSerializer::class)) {
+ throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed.');
+ }
+
+ $loader->load('web_link.xml');
+ }
+
$this->addAnnotatedClassesToCompile(array(
'**Bundle\\Controller\\',
'**Bundle\\Entity\\',
@@ -194,47 +244,85 @@ public function load(array $configs, ContainerBuilder $container)
'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
));
- $this->addClassesToCompile(array(
- 'Symfony\\Component\\Config\\ConfigCache',
- 'Symfony\\Component\\Config\\FileLocator',
-
- 'Symfony\\Component\\Debug\\ErrorHandler',
-
- 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface',
- 'Symfony\\Component\\DependencyInjection\\Container',
-
- 'Symfony\\Component\\EventDispatcher\\Event',
- 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher',
-
- 'Symfony\\Component\\HttpFoundation\\Response',
- 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag',
-
- 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener',
- 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener',
- 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle',
- 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
- 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver',
- 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata',
- 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory',
- 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
- 'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
- 'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',
- 'Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent',
- 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent',
- 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent',
- 'Symfony\\Component\\HttpKernel\\HttpKernel',
- 'Symfony\\Component\\HttpKernel\\KernelEvents',
- 'Symfony\\Component\\HttpKernel\\Config\\FileLocator',
-
- 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser',
- 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
-
- // Cannot be included because annotations will parse the big compiled class file
- // 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
-
- // cannot be included as commands are discovered based on the path to this class via Reflection
- // 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle',
- ));
+ $container->registerForAutoconfiguration(Command::class)
+ ->addTag('console.command');
+ $container->registerForAutoconfiguration(ResourceCheckerInterface::class)
+ ->addTag('config_cache.resource_checker');
+ $container->registerForAutoconfiguration(ServiceSubscriberInterface::class)
+ ->addTag('container.service_subscriber');
+ $container->registerForAutoconfiguration(AbstractController::class)
+ ->addTag('controller.service_arguments');
+ $container->registerForAutoconfiguration(Controller::class)
+ ->addTag('controller.service_arguments');
+ $container->registerForAutoconfiguration(DataCollectorInterface::class)
+ ->addTag('data_collector');
+ $container->registerForAutoconfiguration(FormTypeInterface::class)
+ ->addTag('form.type');
+ $container->registerForAutoconfiguration(FormTypeGuesserInterface::class)
+ ->addTag('form.type_guesser');
+ $container->registerForAutoconfiguration(CacheClearerInterface::class)
+ ->addTag('kernel.cache_clearer');
+ $container->registerForAutoconfiguration(CacheWarmerInterface::class)
+ ->addTag('kernel.cache_warmer');
+ $container->registerForAutoconfiguration(EventSubscriberInterface::class)
+ ->addTag('kernel.event_subscriber');
+ $container->registerForAutoconfiguration(PropertyListExtractorInterface::class)
+ ->addTag('property_info.list_extractor');
+ $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class)
+ ->addTag('property_info.type_extractor');
+ $container->registerForAutoconfiguration(PropertyDescriptionExtractorInterface::class)
+ ->addTag('property_info.description_extractor');
+ $container->registerForAutoconfiguration(PropertyAccessExtractorInterface::class)
+ ->addTag('property_info.access_extractor');
+ $container->registerForAutoconfiguration(EncoderInterface::class)
+ ->addTag('serializer.encoder');
+ $container->registerForAutoconfiguration(NormalizerInterface::class)
+ ->addTag('serializer.normalizer');
+ $container->registerForAutoconfiguration(ConstraintValidatorInterface::class)
+ ->addTag('validator.constraint_validator');
+ $container->registerForAutoconfiguration(ObjectInitializerInterface::class)
+ ->addTag('validator.initializer');
+
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\\Component\\Config\\ConfigCache',
+ 'Symfony\\Component\\Config\\FileLocator',
+
+ 'Symfony\\Component\\Debug\\ErrorHandler',
+
+ 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface',
+ 'Symfony\\Component\\DependencyInjection\\Container',
+
+ 'Symfony\\Component\\EventDispatcher\\Event',
+ 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher',
+
+ 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener',
+ 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener',
+ 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle',
+ 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
+ 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver',
+ 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata',
+ 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory',
+ 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
+ 'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
+ 'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',
+ 'Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent',
+ 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent',
+ 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent',
+ 'Symfony\\Component\\HttpKernel\\HttpKernel',
+ 'Symfony\\Component\\HttpKernel\\KernelEvents',
+ 'Symfony\\Component\\HttpKernel\\Config\\FileLocator',
+
+ 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser',
+ 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
+
+ // Cannot be included because annotations will parse the big compiled class file
+ // 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
+
+ // cannot be included as commands are discovered based on the path to this class via Reflection
+ // 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle',
+ ));
+ }
}
/**
@@ -340,6 +428,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
$loader->load('profiling.xml');
$loader->load('collectors.xml');
+ $loader->load('cache_debug.xml');
if ($this->formConfigEnabled) {
$loader->load('form_debug.xml');
@@ -400,21 +489,29 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
return;
}
+ if (!class_exists(Workflow\Workflow::class)) {
+ throw new LogicException('Workflow support cannot be enabled as the Workflow component is not installed.');
+ }
+
$loader->load('workflow.xml');
$registryDefinition = $container->getDefinition('workflow.registry');
foreach ($workflows as $name => $workflow) {
+ if (!array_key_exists('type', $workflow)) {
+ $workflow['type'] = 'workflow';
+ @trigger_error(sprintf('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.', $name), E_USER_DEPRECATED);
+ }
$type = $workflow['type'];
$transitions = array();
- foreach ($workflow['transitions'] as $transitionName => $transition) {
+ foreach ($workflow['transitions'] as $transition) {
if ($type === 'workflow') {
- $transitions[] = new Definition(Workflow\Transition::class, array($transitionName, $transition['from'], $transition['to']));
+ $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $transition['from'], $transition['to']));
} elseif ($type === 'state_machine') {
foreach ($transition['from'] as $from) {
foreach ($transition['to'] as $to) {
- $transitions[] = new Definition(Workflow\Transition::class, array($transitionName, $from, $to));
+ $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $from, $to));
}
}
}
@@ -436,7 +533,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
// Create MarkingStore
if (isset($workflow['marking_store']['type'])) {
- $markingStoreDefinition = new DefinitionDecorator('workflow.marking_store.'.$workflow['marking_store']['type']);
+ $markingStoreDefinition = new ChildDefinition('workflow.marking_store.'.$workflow['marking_store']['type']);
foreach ($workflow['marking_store']['arguments'] as $argument) {
$markingStoreDefinition->addArgument($argument);
}
@@ -445,7 +542,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
}
// Create Workflow
- $workflowDefinition = new DefinitionDecorator(sprintf('%s.abstract', $type));
+ $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type));
$workflowDefinition->replaceArgument(0, $definitionDefinition);
if (isset($markingStoreDefinition)) {
$workflowDefinition->replaceArgument(1, $markingStoreDefinition);
@@ -458,8 +555,54 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
// Add workflow to Registry
- foreach ($workflow['supports'] as $supportedClass) {
- $registryDefinition->addMethodCall('add', array(new Reference($workflowId), $supportedClass));
+ if ($workflow['supports']) {
+ foreach ($workflow['supports'] as $supportedClassName) {
+ $strategyDefinition = new Definition(Workflow\SupportStrategy\ClassInstanceSupportStrategy::class, array($supportedClassName));
+ $strategyDefinition->setPublic(false);
+ $registryDefinition->addMethodCall('add', array(new Reference($workflowId), $strategyDefinition));
+ }
+ } elseif (isset($workflow['support_strategy'])) {
+ $registryDefinition->addMethodCall('add', array(new Reference($workflowId), new Reference($workflow['support_strategy'])));
+ }
+
+ // Enable the AuditTrail
+ if ($workflow['audit_trail']['enabled']) {
+ $listener = new Definition(Workflow\EventListener\AuditTrailListener::class);
+ $listener->addTag('monolog.logger', array('channel' => 'workflow'));
+ $listener->addTag('kernel.event_listener', array('event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave'));
+ $listener->addTag('kernel.event_listener', array('event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition'));
+ $listener->addTag('kernel.event_listener', array('event' => sprintf('workflow.%s.enter', $name), 'method' => 'onEnter'));
+ $listener->addArgument(new Reference('logger'));
+ $container->setDefinition(sprintf('%s.listener.audit_trail', $workflowId), $listener);
+ }
+
+ // Add Guard Listener
+ $guard = new Definition(Workflow\EventListener\GuardListener::class);
+ $configuration = array();
+ foreach ($workflow['transitions'] as $transitionName => $config) {
+ if (!isset($config['guard'])) {
+ continue;
+ }
+
+ if (!class_exists(ExpressionLanguage::class)) {
+ throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed.');
+ }
+
+ $eventName = sprintf('workflow.%s.guard.%s', $name, $transitionName);
+ $guard->addTag('kernel.event_listener', array('event' => $eventName, 'method' => 'onTransition'));
+ $configuration[$eventName] = $config['guard'];
+ }
+ if ($configuration) {
+ $guard->setArguments(array(
+ $configuration,
+ new Reference('workflow.security.expression_language'),
+ new Reference('security.token_storage'),
+ new Reference('security.authorization_checker'),
+ new Reference('security.authentication.trust_resolver'),
+ new Reference('security.role_hierarchy'),
+ ));
+
+ $container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard);
}
}
}
@@ -479,12 +622,6 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con
if ($debug) {
$loader->load('debug.xml');
-
- // replace the regular event_dispatcher service with the debug one
- $definition = $container->findDefinition('event_dispatcher');
- $definition->setPublic(false);
- $container->setDefinition('debug.event_dispatcher.parent', $definition);
- $container->setAlias('event_dispatcher', 'debug.event_dispatcher');
}
$definition = $container->findDefinition('debug.debug_handlers_listener');
@@ -531,13 +668,15 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
$container->setParameter('request_listener.http_port', $config['http_port']);
$container->setParameter('request_listener.https_port', $config['https_port']);
- $this->addClassesToCompile(array(
- 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
- 'Symfony\\Component\\Routing\\RequestContext',
- 'Symfony\\Component\\Routing\\Router',
- 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableUrlMatcher',
- $container->findDefinition('router.default')->getClass(),
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
+ 'Symfony\\Component\\Routing\\RequestContext',
+ 'Symfony\\Component\\Routing\\Router',
+ 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableUrlMatcher',
+ $container->findDefinition('router.default')->getClass(),
+ ));
+ }
}
/**
@@ -580,20 +719,22 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
$container->setParameter('session.save_path', $config['save_path']);
- $this->addClassesToCompile(array(
- 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
- 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
- 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage',
- 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler',
- 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
- 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy',
- $container->getDefinition('session')->getClass(),
- ));
-
- if ($container->hasDefinition($config['storage_id'])) {
+ if (PHP_VERSION_ID < 70000) {
$this->addClassesToCompile(array(
- $container->findDefinition('session.storage')->getClass(),
+ 'Symfony\\Component\\HttpKernel\\EventListener\\SessionListener',
+ 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
+ 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage',
+ 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler',
+ 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy',
+ 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy',
+ $container->getDefinition('session')->getClass(),
));
+
+ if ($container->hasDefinition($config['storage_id'])) {
+ $this->addClassesToCompile(array(
+ $container->findDefinition('session.storage')->getClass(),
+ ));
+ }
}
$container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']);
@@ -663,12 +804,14 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder
$container->setDefinition('templating.loader', $loaderCache);
}
- $this->addClassesToCompile(array(
- 'Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables',
- 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference',
- 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
- $container->findDefinition('templating.locator')->getClass(),
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables',
+ 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference',
+ 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
+ $container->findDefinition('templating.locator')->getClass(),
+ ));
+ }
$container->setParameter('templating.engines', $config['engines']);
$engines = array_map(function ($engine) { return new Reference('templating.engine.'.$engine); }, $config['engines']);
@@ -701,17 +844,23 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder
$container->setAlias('debug.templating.engine.php', 'templating.engine.php');
}
- $this->addClassesToCompile(array(
- 'Symfony\\Component\\Templating\\Storage\\FileStorage',
- 'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine',
- 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader',
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\\Component\\Templating\\Storage\\FileStorage',
+ 'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine',
+ 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader',
+ ));
+ }
if ($container->has('assets.packages')) {
$container->getDefinition('templating.helper.assets')->replaceArgument(0, new Reference('assets.packages'));
} else {
$container->removeDefinition('templating.helper.assets');
}
+
+ if (!$this->translationConfigEnabled) {
+ $container->removeDefinition('templating.helper.translator');
+ }
}
}
@@ -731,7 +880,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
if ($config['version_strategy']) {
$defaultVersion = new Reference($config['version_strategy']);
} else {
- $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], '_default');
+ $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default');
}
$defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion);
@@ -741,11 +890,14 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
foreach ($config['packages'] as $name => $package) {
if (null !== $package['version_strategy']) {
$version = new Reference($package['version_strategy']);
- } elseif (!array_key_exists('version', $package)) {
+ } elseif (!array_key_exists('version', $package) && null === $package['json_manifest_path']) {
+ // if neither version nor json_manifest_path are specified, use the default
$version = $defaultVersion;
} else {
+ // let format fallback to main version_format
$format = $package['version_format'] ?: $config['version_format'];
- $version = $this->createVersion($container, $package['version'], $format, $name);
+ $version = isset($package['version']) ? $package['version'] : null;
+ $version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name);
}
$container->setDefinition('assets._package_'.$name, $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version));
@@ -767,39 +919,39 @@ private function createPackageDefinition($basePath, array $baseUrls, Reference $
throw new \LogicException('An asset package cannot have base URLs and base paths.');
}
- if (!$baseUrls) {
- $package = new DefinitionDecorator('assets.path_package');
-
- return $package
- ->setPublic(false)
- ->replaceArgument(0, $basePath)
- ->replaceArgument(1, $version)
- ;
- }
-
- $package = new DefinitionDecorator('assets.url_package');
-
- return $package
+ $package = new ChildDefinition($baseUrls ? 'assets.url_package' : 'assets.path_package');
+ $package
->setPublic(false)
- ->replaceArgument(0, $baseUrls)
+ ->replaceArgument(0, $baseUrls ?: $basePath)
->replaceArgument(1, $version)
;
+
+ return $package;
}
- private function createVersion(ContainerBuilder $container, $version, $format, $name)
+ private function createVersion(ContainerBuilder $container, $version, $format, $jsonManifestPath, $name)
{
- if (null === $version) {
- return new Reference('assets.empty_version_strategy');
+ // Configuration prevents $version and $jsonManifestPath from being set
+ if (null !== $version) {
+ $def = new ChildDefinition('assets.static_version_strategy');
+ $def
+ ->replaceArgument(0, $version)
+ ->replaceArgument(1, $format)
+ ;
+ $container->setDefinition('assets._version_'.$name, $def);
+
+ return new Reference('assets._version_'.$name);
}
- $def = new DefinitionDecorator('assets.static_version_strategy');
- $def
- ->replaceArgument(0, $version)
- ->replaceArgument(1, $format)
- ;
- $container->setDefinition('assets._version_'.$name, $def);
+ if (null !== $jsonManifestPath) {
+ $def = new ChildDefinition('assets.json_manifest_version_strategy');
+ $def->replaceArgument(0, $jsonManifestPath);
+ $container->setDefinition('assets._version_'.$name, $def);
- return new Reference('assets._version_'.$name);
+ return new Reference('assets._version_'.$name);
+ }
+
+ return new Reference('assets.empty_version_strategy');
}
/**
@@ -808,17 +960,13 @@ private function createVersion(ContainerBuilder $container, $version, $format, $
* @param array $config A translator configuration array
* @param ContainerBuilder $container A ContainerBuilder instance
*/
- private function registerTranslatorConfiguration(array $config, ContainerBuilder $container)
+ private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader)
{
if (!$this->isConfigEnabled($container, $config)) {
return;
}
- if (!class_exists('Symfony\Component\Translation\Translator')) {
- throw new LogicException('Translation support cannot be enabled as the Translator component is not installed.');
- }
-
- $this->translationConfigEnabled = true;
+ $loader->load('translation.xml');
// Use the "real" translator instead of the identity default
$container->setAlias('translator', 'translator.default');
@@ -845,36 +993,32 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
$dirs[] = dirname(dirname($r->getFileName())).'/Resources/translations';
}
$rootDir = $container->getParameter('kernel.root_dir');
- foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
- $reflection = new \ReflectionClass($class);
- if (is_dir($dir = dirname($reflection->getFileName()).'/Resources/translations')) {
+ foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
+ if ($container->fileExists($dir = $bundle['path'].'/Resources/translations')) {
$dirs[] = $dir;
}
- if (is_dir($dir = $rootDir.sprintf('/Resources/%s/translations', $bundle))) {
+ if ($container->fileExists($dir = $rootDir.sprintf('/Resources/%s/translations', $name))) {
$dirs[] = $dir;
}
}
foreach ($config['paths'] as $dir) {
- if (is_dir($dir)) {
+ if ($container->fileExists($dir)) {
$dirs[] = $dir;
} else {
throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir));
}
}
- if (is_dir($dir = $rootDir.'/Resources/translations')) {
+ if ($container->fileExists($dir = $rootDir.'/Resources/translations')) {
$dirs[] = $dir;
}
// Register translation resources
if ($dirs) {
- foreach ($dirs as $dir) {
- $container->addResource(new DirectoryResource($dir));
- }
-
$files = array();
$finder = Finder::create()
+ ->followLinks()
->files()
->filter(function (\SplFileInfo $file) {
return 2 === substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename());
@@ -892,11 +1036,11 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
}
$options = array_merge(
- $translator->getArgument(3),
+ $translator->getArgument(4),
array('resource_files' => $files)
);
- $translator->replaceArgument(3, $options);
+ $translator->replaceArgument(4, $options);
}
}
@@ -913,19 +1057,25 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
return;
}
+ if (!class_exists('Symfony\Component\Validator\Validation')) {
+ throw new LogicException('Validation support cannot be enabled as the Validator component is not installed.');
+ }
+
$loader->load('validator.xml');
$validatorBuilder = $container->getDefinition('validator.builder');
$container->setParameter('validator.translation_domain', $config['translation_domain']);
- list($xmlMappings, $yamlMappings) = $this->getValidatorMappingFiles($container);
- if (count($xmlMappings) > 0) {
- $validatorBuilder->addMethodCall('addXmlMappings', array($xmlMappings));
+ $files = array('xml' => array(), 'yml' => array());
+ $this->registerValidatorMapping($container, $config, $files);
+
+ if (!empty($files['xml'])) {
+ $validatorBuilder->addMethodCall('addXmlMappings', array($files['xml']));
}
- if (count($yamlMappings) > 0) {
- $validatorBuilder->addMethodCall('addYamlMappings', array($yamlMappings));
+ if (!empty($files['yml'])) {
+ $validatorBuilder->addMethodCall('addYamlMappings', array($files['yml']));
}
$definition = $container->findDefinition('validator.email');
@@ -959,44 +1109,58 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
}
}
- private function getValidatorMappingFiles(ContainerBuilder $container)
+ private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files)
{
- $files = array(array(), array());
+ $fileRecorder = function ($extension, $path) use (&$files) {
+ $files['yaml' === $extension ? 'yml' : $extension][] = $path;
+ };
if (interface_exists('Symfony\Component\Form\FormInterface')) {
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
- $files[0][] = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
- $container->addResource(new FileResource($files[0][0]));
+ $fileRecorder('xml', dirname($reflClass->getFileName()).'/Resources/config/validation.xml');
}
- $bundles = $container->getParameter('kernel.bundles');
- foreach ($bundles as $bundle) {
- $reflection = new \ReflectionClass($bundle);
- $dirname = dirname($reflection->getFileName());
+ foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
+ $dirname = $bundle['path'];
- if (is_file($file = $dirname.'/Resources/config/validation.xml')) {
- $files[0][] = $file;
- $container->addResource(new FileResource($file));
+ if ($container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)) {
+ $fileRecorder('yml', $file);
}
- if (is_file($file = $dirname.'/Resources/config/validation.yml')) {
- $files[1][] = $file;
- $container->addResource(new FileResource($file));
+ if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) {
+ $fileRecorder('xml', $file);
}
- if (is_dir($dir = $dirname.'/Resources/config/validation')) {
- foreach (Finder::create()->files()->in($dir)->name('*.xml') as $file) {
- $files[0][] = $file->getPathname();
- }
- foreach (Finder::create()->files()->in($dir)->name('*.yml') as $file) {
- $files[1][] = $file->getPathname();
- }
-
- $container->addResource(new DirectoryResource($dir));
+ if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) {
+ $this->registerMappingFilesFromDir($dir, $fileRecorder);
}
}
- return $files;
+ $this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
+ }
+
+ private function registerMappingFilesFromDir($dir, callable $fileRecorder)
+ {
+ foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/') as $file) {
+ $fileRecorder($file->getExtension(), $file->getRealPath());
+ }
+ }
+
+ private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder)
+ {
+ foreach ($config['mapping']['paths'] as $path) {
+ if (is_dir($path)) {
+ $this->registerMappingFilesFromDir($path, $fileRecorder);
+ $container->addResource(new DirectoryResource($path, '/^$/'));
+ } elseif ($container->fileExists($path, false)) {
+ if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) {
+ throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path));
+ }
+ $fileRecorder($matches[1], $path);
+ } else {
+ throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path));
+ }
+ }
}
private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, $loader)
@@ -1021,10 +1185,12 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde
$definition = $container->findDefinition('annotations.cache_warmer');
$definition->addTag('kernel.cache_warmer');
- $this->addClassesToCompile(array(
- 'Symfony\Component\Cache\Adapter\PhpArrayAdapter',
- 'Symfony\Component\Cache\DoctrineProvider',
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\Component\Cache\Adapter\PhpArrayAdapter',
+ 'Symfony\Component\Cache\DoctrineProvider',
+ ));
+ }
} elseif ('file' === $config['cache']) {
$cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
@@ -1042,11 +1208,13 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde
$container
->getDefinition('annotations.cached_reader')
- ->replaceArgument(1, new Reference($cacheService))
->replaceArgument(2, $config['debug'])
- ->addAutowiringType(Reader::class)
+ ->addTag('annotations.cached_reader', array('provider' => $cacheService))
;
$container->setAlias('annotation_reader', 'annotations.cached_reader');
+ $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false));
+ } else {
+ $container->removeDefinition('annotations.cached_reader');
}
}
@@ -1146,45 +1314,30 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
$serializerLoaders[] = $annotationLoader;
}
- $bundles = $container->getParameter('kernel.bundles');
- foreach ($bundles as $bundle) {
- $reflection = new \ReflectionClass($bundle);
- $dirname = dirname($reflection->getFileName());
+ $fileRecorder = function ($extension, $path) use (&$serializerLoaders) {
+ $definition = new Definition(in_array($extension, array('yaml', 'yml')) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($path));
+ $definition->setPublic(false);
+ $serializerLoaders[] = $definition;
+ };
- if (is_file($file = $dirname.'/Resources/config/serialization.xml')) {
- $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file));
- $definition->setPublic(false);
+ foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
+ $dirname = $bundle['path'];
- $serializerLoaders[] = $definition;
- $container->addResource(new FileResource($file));
+ if ($container->fileExists($file = $dirname.'/Resources/config/serialization.xml', false)) {
+ $fileRecorder('xml', $file);
}
- if (is_file($file = $dirname.'/Resources/config/serialization.yml')) {
- $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file));
- $definition->setPublic(false);
-
- $serializerLoaders[] = $definition;
- $container->addResource(new FileResource($file));
+ if ($container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)) {
+ $fileRecorder('yml', $file);
}
- 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->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->getPathname()));
- $definition->setPublic(false);
-
- $serializerLoaders[] = $definition;
- }
-
- $container->addResource(new DirectoryResource($dir));
+ if ($container->fileExists($dir = $dirname.'/Resources/config/serialization')) {
+ $this->registerMappingFilesFromDir($dir, $fileRecorder);
}
}
+ $this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
+
$chainLoader->replaceArgument(0, $serializerLoaders);
$container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders);
@@ -1216,6 +1369,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
if (isset($config['name_converter']) && $config['name_converter']) {
$container->getDefinition('serializer.normalizer.object')->replaceArgument(1, new Reference($config['name_converter']));
}
+
+ if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) {
+ $container->getDefinition('serializer.normalizer.object')->addMethodCall('setCircularReferenceHandler', array(new Reference($config['circular_reference_handler'])));
+ }
}
/**
@@ -1239,7 +1396,6 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
private function registerCacheConfiguration(array $config, ContainerBuilder $container)
{
$version = substr(str_replace('/', '-', base64_encode(hash('sha256', uniqid(mt_rand(), true), true))), 0, 22);
- $container->getDefinition('cache.annotations')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.system')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']);
@@ -1247,7 +1403,11 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
if (isset($config['prefix_seed'])) {
$container->setParameter('cache.prefix.seed', $config['prefix_seed']);
}
- foreach (array('doctrine', 'psr6', 'redis') as $name) {
+ if ($container->hasParameter('cache.prefix.seed')) {
+ // Inline any env vars referenced in the parameter
+ $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true));
+ }
+ foreach (array('doctrine', 'psr6', 'redis', 'memcached') as $name) {
if (isset($config[$name = 'default_'.$name.'_provider'])) {
$container->setAlias('cache.'.$name, new Alias(Compiler\CachePoolPass::getServiceProvider($container, $config[$name]), false));
}
@@ -1259,7 +1419,7 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
);
}
foreach ($config['pools'] as $name => $pool) {
- $definition = new DefinitionDecorator($pool['adapter']);
+ $definition = new ChildDefinition($pool['adapter']);
$definition->setPublic($pool['public']);
unset($pool['adapter'], $pool['public']);
@@ -1270,17 +1430,25 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
if (method_exists(PropertyAccessor::class, 'createCache')) {
$propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class);
$propertyAccessDefinition->setPublic(false);
- $propertyAccessDefinition->setFactory(array(PropertyAccessor::class, 'createCache'));
- $propertyAccessDefinition->setArguments(array(null, null, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
- $propertyAccessDefinition->addTag('cache.pool', array('clearer' => 'cache.default_clearer'));
- $propertyAccessDefinition->addTag('monolog.logger', array('channel' => 'cache'));
+
+ if (!$container->getParameter('kernel.debug')) {
+ $propertyAccessDefinition->setFactory(array(PropertyAccessor::class, 'createCache'));
+ $propertyAccessDefinition->setArguments(array(null, null, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
+ $propertyAccessDefinition->addTag('cache.pool', array('clearer' => 'cache.default_clearer'));
+ $propertyAccessDefinition->addTag('monolog.logger', array('channel' => 'cache'));
+ } else {
+ $propertyAccessDefinition->setClass(ArrayAdapter::class);
+ $propertyAccessDefinition->setArguments(array(0, false));
+ }
}
- $this->addClassesToCompile(array(
- 'Symfony\Component\Cache\Adapter\ApcuAdapter',
- 'Symfony\Component\Cache\Adapter\FilesystemAdapter',
- 'Symfony\Component\Cache\CacheItem',
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\Component\Cache\Adapter\ApcuAdapter',
+ 'Symfony\Component\Cache\Adapter\FilesystemAdapter',
+ 'Symfony\Component\Cache\CacheItem',
+ ));
+ }
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
index 6c248d8a42880..92db8ece73ee1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
+++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
@@ -11,19 +11,20 @@
namespace Symfony\Bundle\FrameworkBundle\EventListener;
-use Symfony\Component\HttpKernel\EventListener\SessionListener as BaseSessionListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
+
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\SessionListener instead.', SessionListener::class), E_USER_DEPRECATED);
/**
* Sets the session in the request.
*
* @author Fabien Potencier
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\SessionListener instead
*/
-class SessionListener extends BaseSessionListener
+class SessionListener extends AbstractSessionListener
{
- /**
- * @var ContainerInterface
- */
private $container;
public function __construct(ContainerInterface $container)
diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php
index b32faa2f05668..703be8ff3beda 100644
--- a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php
+++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php
@@ -11,15 +11,19 @@
namespace Symfony\Bundle\FrameworkBundle\EventListener;
-use Symfony\Component\HttpKernel\EventListener\TestSessionListener as BaseTestSessionListener;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\TestSessionListener instead.', TestSessionListener::class), E_USER_DEPRECATED);
+
+use Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* TestSessionListener.
*
* @author Fabien Potencier
+ *
+ * @deprecated since version 3.3, to be removed in 4.0.
*/
-class TestSessionListener extends BaseTestSessionListener
+class TestSessionListener extends AbstractTestSessionListener
{
protected $container;
diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 4c20d146cb4bf..1794a86f92488 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -11,17 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RoutingResolverPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
@@ -29,20 +25,29 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CompilerDebugDumpPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass;
-use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ValidateWorkflowsPass;
+use Symfony\Component\Config\DependencyInjection\ConfigCachePass;
+use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
+use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
+use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
+use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass;
+use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass;
+use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;
+use Symfony\Component\Serializer\DependencyInjection\SerializerPass;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
+use Symfony\Component\Form\DependencyInjection\FormPass;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\Config\Resource\ClassExistenceResource;
+use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
+use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
+use Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass;
/**
* Bundle.
@@ -55,8 +60,12 @@ public function boot()
{
ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true);
- if ($trustedProxies = $this->container->getParameter('kernel.trusted_proxies')) {
- Request::setTrustedProxies($trustedProxies);
+ if ($this->container->hasParameter('kernel.trusted_proxies')) {
+ @trigger_error('The "kernel.trusted_proxies" parameter is deprecated since version 3.3 and will be removed in 4.0. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED);
+
+ if ($trustedProxies = $this->container->getParameter('kernel.trusted_proxies')) {
+ Request::setTrustedProxies($trustedProxies, Request::getTrustedHeaderSet());
+ }
}
if ($this->container->getParameter('kernel.http_method_override')) {
@@ -72,16 +81,18 @@ public function build(ContainerBuilder $container)
{
parent::build($container);
+ $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
+ $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new RoutingResolverPass());
$container->addCompilerPass(new ProfilerPass());
// must be registered before removing private services as some might be listeners/subscribers
// but as late as possible to get resolved parameters
$container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new TemplatingPass());
- $container->addCompilerPass(new AddConstraintValidatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
- $container->addCompilerPass(new AddValidatorInitializersPass());
- $container->addCompilerPass(new AddConsoleCommandPass());
- $container->addCompilerPass(new FormPass());
+ $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class, PassConfig::TYPE_BEFORE_REMOVING);
+ $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
+ $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
+ $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class);
$container->addCompilerPass(new TranslatorPass());
$container->addCompilerPass(new LoggingTranslatorPass());
$container->addCompilerPass(new AddCacheWarmerPass());
@@ -90,19 +101,30 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new TranslationExtractorPass());
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
- $container->addCompilerPass(new SerializerPass());
- $container->addCompilerPass(new PropertyInfoPass());
+ $this->addCompilerPassIfExists($container, SerializerPass::class);
+ $this->addCompilerPassIfExists($container, PropertyInfoPass::class);
+ $container->addCompilerPass(new DataCollectorTranslatorPass());
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
$container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32);
- $container->addCompilerPass(new ValidateWorkflowsPass());
+ $this->addCompilerPassIfExists($container, ValidateWorkflowsPass::class);
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
+ $this->addCompilerPassIfExists($container, FormPass::class);
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
- $container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
- $container->addCompilerPass(new ConfigCachePass());
+ $this->addCompilerPassIfExists($container, ConfigCachePass::class);
+ $container->addCompilerPass(new CacheCollectorPass());
+ }
+ }
+
+ private function addCompilerPassIfExists(ContainerBuilder $container, $class, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, $priority = 0)
+ {
+ $container->addResource(new ClassExistenceResource($class));
+
+ if (class_exists($class)) {
+ $container->addCompilerPass(new $class(), $type, $priority);
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/LICENSE b/src/Symfony/Bundle/FrameworkBundle/LICENSE
index 12a74531e40a4..17d16a13367dd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/LICENSE
+++ b/src/Symfony/Bundle/FrameworkBundle/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2016 Fabien Potencier
+Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml
index a2a0fb4065329..f3f4e0bd6114b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml
@@ -6,12 +6,25 @@
- Doctrine\Common\Annotations\Reader
+
+ required
+
+
+
+
+ class_exists
+
+
+
+
+
-
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml
index 4f2e1fbf362a0..e83afa7cf4148 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml
@@ -10,6 +10,7 @@
+
@@ -21,13 +22,13 @@
-
+
-
+
@@ -38,5 +39,9 @@
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
index 80cb00ada9652..72eca553f58af 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
@@ -22,13 +22,8 @@
-
-
-
-
- 0
-
- %kernel.cache_dir%/pools
+
+
@@ -93,11 +88,24 @@
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml
new file mode 100644
index 0000000000000..3d68472028e93
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
index afebe6da98fd8..340c7e1972801 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
@@ -32,6 +32,7 @@
+ %kernel.cache_dir%/%kernel.container_class%
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml
new file mode 100644
index 0000000000000..350c2e20ef7a7
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml
index 073851b038e67..3d260e4aff728 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml
@@ -9,9 +9,9 @@
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml
index 51d374338e0b2..76c143b74e93e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml
@@ -22,9 +22,11 @@
+
%debug.file_link_format%
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
index d26c00cd50282..a9eb59b4782a4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
@@ -7,6 +7,7 @@
+
@@ -21,26 +22,25 @@
+
+
-
-
-
-
-
-
-
+
+
+
+ null
-
+
@@ -61,7 +61,7 @@
-
+
@@ -71,7 +71,7 @@
The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.
-
+
@@ -158,7 +158,7 @@
-
+
@@ -173,20 +173,34 @@
-
+
-
+
-
+
-
+
%validator.translation_domain%
+
+
+
+
+
+
+
+
+
+
+
+
+ The service "%service_id%" is internal and deprecated since Symfony 3.3 and will be removed in Symfony 4.0
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
index a562931a5e9a4..e4363184b95e4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
@@ -5,14 +5,22 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
+
%form.type_extension.csrf.enabled%
%form.type_extension.csrf.field_name%
-
+
%validator.translation_domain%
+
+
+
+
+
+ The service "%service_id%" is internal and deprecated since Symfony 3.3 and will be removed in Symfony 4.0
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
index 843fc72bdb253..00e7c34e5e10d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
index 3f0d319d9de13..963179c64e99e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
@@ -11,7 +11,7 @@
-
+
%kernel.debug%
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/identity_translator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/identity_translator.xml
new file mode 100644
index 0000000000000..542d6248db4d5
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/identity_translator.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml
index d9e381c4806b8..af81e9dd0658b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml
@@ -10,5 +10,6 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
index 33a0a661f8991..81e1037052b21 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
@@ -11,11 +11,12 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_prod.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_prod.php
deleted file mode 100644
index 97613a6248f71..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_prod.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * This file implements rewrite rules for PHP built-in web server.
- *
- * See: http://www.php.net/manual/en/features.commandline.webserver.php
- *
- * If you have custom directory layout, then you have to write your own router
- * and pass it as a value to 'router' option of server:run command.
- *
- * @author: Michał Pipa
- * @author: Albert Jessurum
- */
-
-// Workaround https://bugs.php.net/64566
-if (ini_get('auto_prepend_file') && !in_array(realpath(ini_get('auto_prepend_file')), get_included_files(), true)) {
- require ini_get('auto_prepend_file');
-}
-
-if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'])) {
- return false;
-}
-
-$_SERVER = array_merge($_SERVER, $_ENV);
-$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app.php';
-
-// Since we are rewriting to app.php, adjust SCRIPT_NAME and PHP_SELF accordingly
-$_SERVER['SCRIPT_NAME'] = DIRECTORY_SEPARATOR.'app.php';
-$_SERVER['PHP_SELF'] = DIRECTORY_SEPARATOR.'app.php';
-
-require 'app.php';
-
-error_log(sprintf('%s:%d [%d]: %s', $_SERVER['REMOTE_ADDR'], $_SERVER['REMOTE_PORT'], http_response_code(), $_SERVER['REQUEST_URI']), 4);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_test.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_test.php
deleted file mode 100644
index 5b020d5d22977..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_test.php
+++ /dev/null
@@ -1,31 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/*
- * This file implements rewrite rules for PHP built-in web server.
- *
- * See: http://www.php.net/manual/en/features.commandline.webserver.php
- *
- * If you have custom directory layout, then you have to write your own router
- * and pass it as a value to 'router' option of server:run command.
- *
- * @author: Michał Pipa
- * @author: Albert Jessurum
- */
-
-if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'])) {
- return false;
-}
-
-$_SERVER = array_merge($_SERVER, $_ENV);
-$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app_test.php';
-
-require 'app_test.php';
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
index 6050686d6c3c5..0befbe91c2a72 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -36,6 +36,11 @@
+
+
+
+
+
@@ -75,6 +80,9 @@
+
+
+
%router.request_context.base_url%
@@ -84,6 +92,7 @@
%request_listener.http_port%
%request_listener.https_port%
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index fbf53309f41be..29d07c5758eed 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -14,6 +14,7 @@
+
@@ -62,6 +63,10 @@
+
+
+
+
@@ -131,6 +136,7 @@
+
@@ -143,6 +149,7 @@
+
@@ -176,6 +183,7 @@
+
@@ -184,6 +192,12 @@
+
+
+
+
+
+
@@ -197,6 +211,9 @@
+
+
+
@@ -215,6 +232,7 @@
+
@@ -231,13 +249,14 @@
-
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/security_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/security_csrf.xml
index 354b515076968..489028d3f7b2b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/security_csrf.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/security_csrf.xml
@@ -6,14 +6,17 @@
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
index 5370d38072536..518164cf8a891 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
@@ -14,6 +14,11 @@
+
+
+
+
+
@@ -27,6 +32,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
index f07f5261bb40a..86e3f597a1d27 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
@@ -8,6 +8,7 @@
+
@@ -15,15 +16,16 @@
+
+
-
Symfony\Component\HttpFoundation\ParameterBag
Symfony\Component\HttpFoundation\HeaderBag
@@ -31,35 +33,40 @@
Symfony\Component\HttpFoundation\ServerBag
Symfony\Component\HttpFoundation\Request
Symfony\Component\HttpKernel\Kernel
- Symfony\Component\ClassLoader\ClassCollectionLoader
- Symfony\Component\ClassLoader\ApcClassLoader
+ The "%service_id%" option is deprecated since version 3.3, to be removed in 4.0.
-
- Symfony\Component\DependencyInjection\ContainerInterface
- Symfony\Component\DependencyInjection\Container
-
-
+
+
%kernel.root_dir%/Resources
+
+ %kernel.root_dir%
+
+
%kernel.secret%
-
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
index 2a4816a2b3bf1..55180b6027222 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
@@ -15,6 +15,10 @@
+
+
+
+
%session.metadata.storage_key%
%session.metadata.update_threshold%
@@ -47,9 +51,16 @@
-
+
-
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
index ebb311ceb0808..719c84aa1039a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
@@ -20,9 +20,16 @@
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
index ba1c3bc168316..2fa53885b9d8f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
@@ -6,20 +6,19 @@
-
+
-
+ %kernel.default_locale%
+
%kernel.cache_dir%/translations
%kernel.debug%
-
-
- Symfony\Component\Translation\TranslatorInterface
+
@@ -27,12 +26,6 @@
-
-
-
-
-
-
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
index 6da59e54e212e..2fb73fa39bbd6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
@@ -13,6 +13,7 @@
+
@@ -57,8 +58,7 @@
-
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
index 72a200b313fa4..9bc44418cf52a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
@@ -21,7 +21,7 @@
-
+
@@ -32,6 +32,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.xml
new file mode 100644
index 0000000000000..b80708defed13
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml
index 76592087a2260..0e79543ac6433 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml
@@ -22,10 +22,13 @@
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php
index eb421be817691..a9bd62f2a1b9e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php
@@ -1 +1,9 @@
-block($form, 'widget_attributes') ?>
+ $v): ?>
+
+escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
+
+escape($k), $view->escape($k)) ?>
+
+escape($k), $view->escape($v)) ?>
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/button_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/button_attributes.html.php
index 2be960d0e179c..279233baa3fc0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/button_attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/button_attributes.html.php
@@ -1,10 +1,2 @@
-id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled"
- $v): ?>
-
-escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
-
-escape($k), $view->escape($k)) ?>
-
-escape($k), $view->escape($v)) ?>
-
-
+id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled"
+block($form, 'attributes') : '' ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php
index 7a51b2ce7b4ff..78c953ec5a1f3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_label.html.php
@@ -4,5 +4,5 @@
$name, '%id%' => $id))
: $view['form']->humanize($name); } ?>
- $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>>escape(false !== $translation_domain ? $view['translator']->trans($label, array(), $translation_domain) : $label) ?>
+block($form, 'attributes', array('attr' => $label_attr)); } ?>>escape(false !== $translation_domain ? $view['translator']->trans($label, array(), $translation_domain) : $label) ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
index 3fefa47c15c99..41c0cc7bfe8ba 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
@@ -1,11 +1,3 @@
id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled"
required="required"
- $v): ?>
-
-escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
-
-escape($k), $view->escape($k)) ?>
-
-escape($k), $view->escape($v)) ?>
-
-
+block($form, 'attributes') : '' ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_container_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_container_attributes.html.php
index dc2e5ebea84e6..fdd176d12c79f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_container_attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_container_attributes.html.php
@@ -1,10 +1,2 @@
-id="escape($id) ?>"
- $v): ?>
-
-escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
-
-escape($k), $view->escape($k)) ?>
-
-escape($k), $view->escape($v)) ?>
-
-
+id="escape($id) ?>"
+block($form, 'attributes') : '' ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
index 9783117f0b7f6..fce47e9eb8426 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php
@@ -64,7 +64,7 @@ public function load($resource, $type = null)
// - this handles the case and prevents the second fatal error
// by triggering an exception beforehand.
- throw new FileLoaderLoadException($resource);
+ throw new FileLoaderLoadException($resource, null, null, null, $type);
}
$this->loading = true;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php
index 35bd5ef1efed0..afc2ebe1a4e49 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php
@@ -11,6 +11,9 @@
namespace Symfony\Bundle\FrameworkBundle\Routing;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\DependencyInjection\Config\ContainerParametersResource;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
use Symfony\Component\Routing\Router as BaseRouter;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -24,9 +27,10 @@
*
* @author Fabien Potencier
*/
-class Router extends BaseRouter implements WarmableInterface
+class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface
{
private $container;
+ private $collectedParameters = array();
/**
* Constructor.
@@ -53,6 +57,7 @@ public function getRouteCollection()
if (null === $this->collection) {
$this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']);
$this->resolveParameters($this->collection);
+ $this->collection->addResource(new ContainerParametersResource($this->collectedParameters));
}
return $this->collection;
@@ -153,6 +158,8 @@ private function resolve($value)
$resolved = $container->getParameter($match[1]);
if (is_string($resolved) || is_numeric($resolved)) {
+ $this->collectedParameters[$match[1]] = $resolved;
+
return (string) $resolved;
}
@@ -168,4 +175,14 @@ private function resolve($value)
return str_replace('%%', '%', $escapedValue);
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedServices()
+ {
+ return array(
+ 'routing.loader' => LoaderInterface::class,
+ );
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php
index c204ffa2f03b2..1104cd73634c3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php
@@ -11,8 +11,8 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Templating\DelegatingEngine as BaseDelegatingEngine;
-use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/GlobalVariables.php b/src/Symfony/Bundle/FrameworkBundle/Templating/GlobalVariables.php
index 606e886415c95..5ebfea1793784 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/GlobalVariables.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/GlobalVariables.php
@@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* GlobalVariables is the entry point for Symfony global variables in PHP templates.
@@ -33,21 +34,20 @@ public function __construct(ContainerInterface $container)
}
/**
- * Returns the current user.
- *
- * @return mixed
- *
- * @see TokenInterface::getUser()
+ * @return TokenInterface|null
*/
- public function getUser()
+ public function getToken()
{
if (!$this->container->has('security.token_storage')) {
return;
}
- $tokenStorage = $this->container->get('security.token_storage');
+ return $this->container->get('security.token_storage')->getToken();
+ }
- if (!$token = $tokenStorage->getToken()) {
+ public function getUser()
+ {
+ if (!$token = $this->getToken()) {
return;
}
@@ -60,8 +60,6 @@ public function getUser()
}
/**
- * Returns the current request.
- *
* @return Request|null The HTTP request object
*/
public function getRequest()
@@ -72,8 +70,6 @@ public function getRequest()
}
/**
- * Returns the current session.
- *
* @return Session|null The session
*/
public function getSession()
@@ -84,8 +80,6 @@ public function getSession()
}
/**
- * Returns the current app environment.
- *
* @return string The current environment string (e.g 'dev')
*/
public function getEnvironment()
@@ -94,8 +88,6 @@ public function getEnvironment()
}
/**
- * Returns the current app debug mode.
- *
* @return bool The current debug mode
*/
public function getDebug()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php
index c4085e4ec0f93..ba36cbde0c884 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php
@@ -133,7 +133,7 @@ public function fileExcerpt($file, $line)
$code = @highlight_file($file, true);
// remove main code/span tags
$code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code);
- $content = preg_split('# #', $code);
+ $content = explode(' ', $code);
$lines = array();
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; ++$i) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php
index bf6e795d80cc8..31fd9a368ff72 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php
@@ -24,6 +24,8 @@ class TemplateLocator implements FileLocatorInterface
protected $locator;
protected $cache;
+ private $cacheHits = array();
+
/**
* Constructor.
*
@@ -71,12 +73,15 @@ public function locate($template, $currentPath = null, $first = true)
$key = $this->getCacheKey($template);
+ if (isset($this->cacheHits[$key])) {
+ return $this->cacheHits[$key];
+ }
if (isset($this->cache[$key])) {
- return $this->cache[$key];
+ return $this->cacheHits[$key] = realpath($this->cache[$key]) ?: $this->cache[$key];
}
try {
- return $this->cache[$key] = $this->locator->locate($template->getPath(), $currentPath);
+ return $this->cacheHits[$key] = $this->locator->locate($template->getPath(), $currentPath);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException(sprintf('Unable to find template "%s" : "%s".', $template, $e->getMessage()), 0, $e);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php
index 41382f769c65f..f9f5a5215fdfe 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php
@@ -11,10 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Templating\PhpEngine as BasePhpEngine;
use Symfony\Component\Templating\Loader\LoaderInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php
index 3295cc73a726f..6ab1b507ca264 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php
@@ -11,10 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Templating\Loader\LoaderInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Times the time spent to render a template.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
index 7f8de034f94b9..b8ec208c1dbe4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Test;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\KernelInterface;
@@ -20,7 +21,7 @@
*
* @author Fabien Potencier
*/
-abstract class KernelTestCase extends \PHPUnit_Framework_TestCase
+abstract class KernelTestCase extends TestCase
{
protected static $class;
@@ -137,6 +138,8 @@ protected static function getKernelClass()
* Boots the Kernel for this test.
*
* @param array $options
+ *
+ * @return KernelInterface A KernelInterface instance
*/
protected static function bootKernel(array $options = array())
{
@@ -144,6 +147,8 @@ protected static function bootKernel(array $options = array())
static::$kernel = static::createKernel($options);
static::$kernel->boot();
+
+ return static::$kernel;
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php
index 5708ef716df7b..e62e2921a1875 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php
@@ -30,9 +30,9 @@ abstract class WebTestCase extends KernelTestCase
*/
protected static function createClient(array $options = array(), array $server = array())
{
- static::bootKernel($options);
+ $kernel = static::bootKernel($options);
- $client = static::$kernel->getContainer()->get('test.client');
+ $client = $kernel->getContainer()->get('test.client');
$client->setServerParameters($server);
return $client;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php
index 889601b01fa6f..5e442d662f12a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php
@@ -16,6 +16,9 @@
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\WarmedClass;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
+/**
+ * @group legacy
+ */
class ClassCacheCacheWarmerTest extends TestCase
{
public function testWithDeclaredClasses()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/TemplatePathsCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/TemplatePathsCacheWarmerTest.php
index 062210d3a0585..74a33f3b43130 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/TemplatePathsCacheWarmerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/TemplatePathsCacheWarmerTest.php
@@ -35,7 +35,7 @@ class TemplatePathsCacheWarmerTest extends TestCase
private $tmpDir;
- public function setUp()
+ protected function setUp()
{
$this->templateFinder = $this
->getMockBuilder(TemplateFinderInterface::class)
@@ -56,7 +56,7 @@ public function setUp()
$this->filesystem->mkdir($this->tmpDir);
}
- public function tearDown()
+ protected function tearDown()
{
$this->filesystem->remove($this->tmpDir);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php
index 0e3fe47ce5ff8..23b4732afcb3a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php
@@ -51,6 +51,39 @@ public function testWarmUp()
$this->assertArrayHasKey('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Author', $values);
}
+ public function testWarmUpWithAnnotations()
+ {
+ $validatorBuilder = new ValidatorBuilder();
+ $validatorBuilder->addYamlMapping(__DIR__.'/../Fixtures/Validation/Resources/categories.yml');
+ $validatorBuilder->enableAnnotationMapping();
+
+ $file = sys_get_temp_dir().'/cache-validator-with-annotations.php';
+ @unlink($file);
+
+ $fallbackPool = new ArrayAdapter();
+
+ $warmer = new ValidatorCacheWarmer($validatorBuilder, $file, $fallbackPool);
+ $warmer->warmUp(dirname($file));
+
+ $this->assertFileExists($file);
+
+ $values = require $file;
+
+ $this->assertInternalType('array', $values);
+ $this->assertCount(1, $values);
+ $this->assertArrayHasKey('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Category', $values);
+
+ // Simple check to make sure that at least one constraint is actually cached, in this case the "id" property Type.
+ $this->assertContains('"int"', $values['Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Category']);
+
+ $values = $fallbackPool->getValues();
+
+ $this->assertInternalType('array', $values);
+ $this->assertCount(2, $values);
+ $this->assertArrayHasKey('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Category', $values);
+ $this->assertArrayHasKey('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.SubCategory', $values);
+ }
+
public function testWarmUpWithoutLoader()
{
$validatorBuilder = new ValidatorBuilder();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
index ba969c64ae1f4..b9fe63ec5bbab 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
@@ -43,6 +43,9 @@ protected function tearDown()
$this->fs->remove($this->rootDir);
}
+ /**
+ * @group legacy
+ */
public function testCacheIsFreshAfterCacheClearedWithWarmup()
{
$input = new ArrayInput(array('cache:clear'));
@@ -57,11 +60,10 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup()
// simply check that cache is warmed up
$this->assertGreaterThanOrEqual(1, count($metaFiles));
$configCacheFactory = new ConfigCacheFactory(true);
- $that = $this;
foreach ($metaFiles as $file) {
- $configCacheFactory->cache(substr($file, 0, -5), function () use ($that, $file) {
- $that->fail(sprintf('Meta file "%s" is not fresh', (string) $file));
+ $configCacheFactory->cache(substr($file, 0, -5), function () use ($file) {
+ $this->fail(sprintf('Meta file "%s" is not fresh', (string) $file));
});
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php
index e42babd362404..a0cac9a908b24 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
-class RouterDebugCommandTest extends \PHPUnit_Framework_TestCase
+class RouterDebugCommandTest extends TestCase
{
public function testDebugAllRoutes()
{
@@ -63,7 +64,7 @@ private function getContainer()
{
$routeCollection = new RouteCollection();
$routeCollection->add('foo', new Route('foo'));
- $router = $this->getMock('Symfony\Component\Routing\RouterInterface');
+ $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router
->expects($this->any())
->method('getRouteCollection')
@@ -74,7 +75,7 @@ private function getContainer()
->disableOriginalConstructor()
->getMock();
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('has')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php
index 3dc64a300e8c6..db533c09742ba 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand;
@@ -19,7 +20,7 @@
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
-class RouterMatchCommandTest extends \PHPUnit_Framework_TestCase
+class RouterMatchCommandTest extends TestCase
{
public function testWithMatchPath()
{
@@ -62,7 +63,7 @@ private function getContainer()
$routeCollection = new RouteCollection();
$routeCollection->add('foo', new Route('foo'));
$requestContext = new RequestContext();
- $router = $this->getMock('Symfony\Component\Routing\RouterInterface');
+ $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router
->expects($this->any())
->method('getRouteCollection')
@@ -78,7 +79,7 @@ private function getContainer()
->disableOriginalConstructor()
->getMock();
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('has')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php
index 27f61c4383f24..19c6d70156b19 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand;
use Symfony\Component\Filesystem\Filesystem;
-class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
+class TranslationDebugCommandTest extends TestCase
{
private $fs;
private $translationDir;
@@ -64,7 +65,7 @@ public function testDebugDefaultDirectory()
public function testDebugCustomDirectory()
{
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel->expects($this->once())
->method('getBundle')
->with($this->equalTo($this->translationDir))
@@ -82,7 +83,7 @@ public function testDebugCustomDirectory()
*/
public function testDebugInvalidDirectory()
{
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel->expects($this->once())
->method('getBundle')
->with($this->equalTo('dir'))
@@ -130,7 +131,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
->method('getFallbackLocales')
->will($this->returnValue(array('en')));
- $extractor = $this->getMock('Symfony\Component\Translation\Extractor\ExtractorInterface');
+ $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock();
$extractor
->expects($this->any())
->method('extract')
@@ -140,7 +141,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
})
);
- $loader = $this->getMock('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader');
+ $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock();
$loader
->expects($this->any())
->method('loadMessages')
@@ -151,7 +152,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
);
if (null === $kernel) {
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundle')
@@ -166,7 +167,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
->method('getRootDir')
->will($this->returnValue($this->translationDir));
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->any())
->method('get')
@@ -182,7 +183,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
private function getBundle($path)
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
$bundle
->expects($this->any())
->method('getPath')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php
index c876ee415de3c..e845619d9a826 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand;
@@ -18,7 +19,7 @@
use Symfony\Component\DependencyInjection;
use Symfony\Component\HttpKernel;
-class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
+class TranslationUpdateCommandTest extends TestCase
{
private $fs;
private $translationDir;
@@ -100,7 +101,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
->method('getFallbackLocales')
->will($this->returnValue(array('en')));
- $extractor = $this->getMock('Symfony\Component\Translation\Extractor\ExtractorInterface');
+ $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock();
$extractor
->expects($this->any())
->method('extract')
@@ -112,7 +113,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
})
);
- $loader = $this->getMock('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader');
+ $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock();
$loader
->expects($this->any())
->method('loadMessages')
@@ -122,7 +123,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
})
);
- $writer = $this->getMock('Symfony\Component\Translation\Writer\TranslationWriter');
+ $writer = $this->getMockBuilder('Symfony\Component\Translation\Writer\TranslationWriter')->getMock();
$writer
->expects($this->any())
->method('getFormats')
@@ -131,7 +132,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
);
if (null === $kernel) {
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundle')
@@ -146,7 +147,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
->method('getRootDir')
->will($this->returnValue($this->translationDir));
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->any())
->method('get')
@@ -163,7 +164,7 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar
private function getBundle($path)
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
$bundle
->expects($this->any())
->method('getPath')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php
index 30ffa76c23e81..de57b816eb4b8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Application as BaseApplication;
@@ -25,7 +26,7 @@
*
* @author Robin Chalas
*/
-class YamlLintCommandTest extends \PHPUnit_Framework_TestCase
+class YamlLintCommandTest extends TestCase
{
private $files;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php
index fc0e7654db2ca..fc60fd3bdd71c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php
@@ -22,7 +22,7 @@ class ApplicationTest extends TestCase
{
public function testBundleInterfaceImplementation()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
$kernel = $this->getKernel(array($bundle), true);
@@ -32,8 +32,7 @@ public function testBundleInterfaceImplementation()
public function testBundleCommandsAreRegistered()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
- $bundle->expects($this->once())->method('registerCommands');
+ $bundle = $this->createBundleMock(array());
$kernel = $this->getKernel(array($bundle), true);
@@ -46,8 +45,7 @@ public function testBundleCommandsAreRegistered()
public function testBundleCommandsAreRetrievable()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
- $bundle->expects($this->once())->method('registerCommands');
+ $bundle = $this->createBundleMock(array());
$kernel = $this->getKernel(array($bundle));
@@ -60,47 +58,41 @@ public function testBundleCommandsAreRetrievable()
public function testBundleSingleCommandIsRetrievable()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
- $bundle->expects($this->once())->method('registerCommands');
+ $command = new Command('example');
+
+ $bundle = $this->createBundleMock(array($command));
$kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
- $command = new Command('example');
- $application->add($command);
-
$this->assertSame($command, $application->get('example'));
}
public function testBundleCommandCanBeFound()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
- $bundle->expects($this->once())->method('registerCommands');
+ $command = new Command('example');
+
+ $bundle = $this->createBundleMock(array($command));
$kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
- $command = new Command('example');
- $application->add($command);
-
$this->assertSame($command, $application->find('example'));
}
public function testBundleCommandCanBeFoundByAlias()
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle');
- $bundle->expects($this->once())->method('registerCommands');
+ $command = new Command('example');
+ $command->setAliases(array('alias'));
+
+ $bundle = $this->createBundleMock(array($command));
$kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
- $command = new Command('example');
- $command->setAliases(array('alias'));
- $application->add($command);
-
$this->assertSame($command, $application->find('alias'));
}
@@ -125,10 +117,10 @@ public function testBundleCommandsHaveRightContainer()
private function getKernel(array $bundles, $useDispatcher = false)
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
if ($useDispatcher) {
- $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$dispatcher
->expects($this->atLeastOnce())
->method('dispatch')
@@ -153,7 +145,7 @@ private function getKernel(array $bundles, $useDispatcher = false)
->will($this->returnValue(array()))
;
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundles')
@@ -167,4 +159,18 @@ private function getKernel(array $bundles, $useDispatcher = false)
return $kernel;
}
+
+ private function createBundleMock(array $commands)
+ {
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle')->getMock();
+ $bundle
+ ->expects($this->once())
+ ->method('registerCommands')
+ ->will($this->returnCallback(function (Application $application) use ($commands) {
+ $application->addCommands($commands);
+ }))
+ ;
+
+ return $bundle;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
index 78a770da85a05..32b70a0829efb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -22,7 +23,7 @@
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
-abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
+abstract class AbstractDescriptorTest extends TestCase
{
/** @dataProvider getDescribeRouteCollectionTestData */
public function testDescribeRouteCollection(RouteCollection $routes, $expectedDescription)
@@ -79,6 +80,24 @@ public function getDescribeContainerDefinitionTestData()
return $this->getDescriptionTestData(ObjectsProvider::getContainerDefinitions());
}
+ /** @dataProvider getDescribeContainerDefinitionWithArgumentsShownTestData */
+ public function testDescribeContainerDefinitionWithArgumentsShown(Definition $definition, $expectedDescription)
+ {
+ $this->assertDescription($expectedDescription, $definition, array('show_arguments' => true));
+ }
+
+ public function getDescribeContainerDefinitionWithArgumentsShownTestData()
+ {
+ $definitions = ObjectsProvider::getContainerDefinitions();
+ $definitionsWithArgs = array();
+
+ foreach ($definitions as $key => $definition) {
+ $definitionsWithArgs[str_replace('definition_', 'definition_arguments_', $key)] = $definition;
+ }
+
+ return $this->getDescriptionTestData($definitionsWithArgs);
+ }
+
/** @dataProvider getDescribeContainerAliasTestData */
public function testDescribeContainerAlias(Alias $alias, $expectedDescription)
{
@@ -90,6 +109,35 @@ public function getDescribeContainerAliasTestData()
return $this->getDescriptionTestData(ObjectsProvider::getContainerAliases());
}
+ /** @dataProvider getDescribeContainerDefinitionWhichIsAnAliasTestData */
+ public function testDescribeContainerDefinitionWhichIsAnAlias(Alias $alias, $expectedDescription, ContainerBuilder $builder, $options = array())
+ {
+ $this->assertDescription($expectedDescription, $builder, $options);
+ }
+
+ public function getDescribeContainerDefinitionWhichIsAnAliasTestData()
+ {
+ $builder = current(ObjectsProvider::getContainerBuilders());
+ $builder->setDefinition('service_1', $builder->getDefinition('definition_1'));
+ $builder->setDefinition('service_2', $builder->getDefinition('definition_2'));
+
+ $aliases = ObjectsProvider::getContainerAliases();
+ $aliasesWithDefinitions = array();
+ foreach ($aliases as $name => $alias) {
+ $aliasesWithDefinitions[str_replace('alias_', 'alias_with_definition_', $name)] = $alias;
+ }
+
+ $i = 0;
+ $data = $this->getDescriptionTestData($aliasesWithDefinitions);
+ foreach ($aliases as $name => $alias) {
+ $data[$i][] = $builder;
+ $data[$i][] = array('id' => $name);
+ ++$i;
+ }
+
+ return $data;
+ }
+
/** @dataProvider getDescribeContainerParameterTestData */
public function testDescribeContainerParameter($parameter, $expectedDescription, array $options)
{
@@ -144,7 +192,7 @@ private function assertDescription($expectedDescription, $describedObject, array
$this->getDescriptor()->describe($output, $describedObject, $options);
if ('json' === $this->getFormat()) {
- $this->assertEquals(json_decode($expectedDescription), json_decode($output->fetch()));
+ $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($output->fetch()), JSON_PRETTY_PRINT));
} else {
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
}
@@ -168,6 +216,7 @@ private function getContainerBuilderDescriptionTestData(array $objects)
'public' => array('show_private' => false),
'tag1' => array('show_private' => true, 'tag' => 'tag1'),
'tags' => array('group_by' => 'tags', 'show_private' => true),
+ 'arguments' => array('show_private' => false, 'show_arguments' => true),
);
$data = array();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
index 5244072ae85cd..0c0363c482bab 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
@@ -12,6 +12,8 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -105,6 +107,19 @@ public static function getContainerDefinitions()
->setSynthetic(false)
->setLazy(true)
->setAbstract(true)
+ ->addArgument(new Reference('definition2'))
+ ->addArgument('%parameter%')
+ ->addArgument(new Definition('inline_service', array('arg1', 'arg2')))
+ ->addArgument(array(
+ 'foo',
+ new Reference('definition2'),
+ new Definition('inline_service'),
+ ))
+ ->addArgument(new IteratorArgument(array(
+ new Reference('definition_1'),
+ new Reference('definition_2'),
+ )))
+ ->addArgument(new ClosureProxyArgument('definition1', 'get'))
->setFactory(array('Full\\Qualified\\FactoryClass', 'get')),
'definition_2' => $definition2
->setPublic(false)
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php
index ce4f377c508fd..e775ac7cf199a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php
@@ -15,6 +15,16 @@
class TextDescriptorTest extends AbstractDescriptorTest
{
+ protected function setUp()
+ {
+ putenv('COLUMNS=121');
+ }
+
+ protected function tearDown()
+ {
+ putenv('COLUMNS');
+ }
+
protected function getDescriptor()
{
return new TextDescriptor();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php
new file mode 100644
index 0000000000000..937cbfc7286d0
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
+
+use Psr\Container\ContainerInterface;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\File\File;
+
+class AbstractControllerTest extends ControllerTraitTest
+{
+ protected function createController()
+ {
+ return new TestAbstractController();
+ }
+}
+
+class TestAbstractController extends AbstractController
+{
+ use TestControllerTrait;
+
+ private $throwOnUnexpectedService;
+
+ public function __construct($throwOnUnexpectedService = true)
+ {
+ $this->throwOnUnexpectedService = $throwOnUnexpectedService;
+ }
+
+ public function setContainer(ContainerInterface $container)
+ {
+ if (!$this->throwOnUnexpectedService) {
+ return parent::setContainer($container);
+ }
+
+ $expected = self::getSubscribedServices();
+
+ foreach ($container->getServiceIds() as $id) {
+ if ('service_container' === $id) {
+ continue;
+ }
+ if (!isset($expected[$id])) {
+ throw new \UnexpectedValueException(sprintf('Service "%s" is not expected, as declared by %s::getSubscribedServices()', $id, AbstractController::class));
+ }
+ $type = substr($expected[$id], 1);
+ if (!$container->get($id) instanceof $type) {
+ throw new \UnexpectedValueException(sprintf('Service "%s" is expected to be an instance of "%s", as declared by %s::getSubscribedServices()', $id, $type, AbstractController::class));
+ }
+ }
+
+ return parent::setContainer($container);
+ }
+
+ public function fooAction()
+ {
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
index 894e7ae3285d3..57eaf269f4424 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
@@ -11,9 +11,9 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
+use Composer\Autoload\ClassLoader;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
-use Symfony\Component\ClassLoader\ClassLoader;
class ControllerNameParserTest extends TestCase
{
@@ -22,17 +22,14 @@ class ControllerNameParserTest extends TestCase
protected function setUp()
{
$this->loader = new ClassLoader();
- $this->loader->addPrefixes(array(
- 'TestBundle' => __DIR__.'/../Fixtures',
- 'TestApplication' => __DIR__.'/../Fixtures',
- ));
+ $this->loader->add('TestBundle', __DIR__.'/../Fixtures');
+ $this->loader->add('TestApplication', __DIR__.'/../Fixtures');
$this->loader->register();
}
protected function tearDown()
{
- spl_autoload_unregister(array($this->loader, 'loadClass'));
-
+ $this->loader->unregister();
$this->loader = null;
}
@@ -147,7 +144,7 @@ private function createParser()
'FabpotFooBundle' => array($this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), $this->getBundle('TestBundle\Sensio\FooBundle', 'SensioFooBundle')),
);
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundle')
@@ -178,7 +175,7 @@ private function createParser()
private function getBundle($namespace, $name)
{
- $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock();
$bundle->expects($this->any())->method('getName')->will($this->returnValue($name));
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue($namespace));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
index b511f90d17adb..7946a96e8d2c0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
@@ -11,15 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
+use Psr\Container\ContainerInterface as Psr11ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver;
+use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest as BaseControllerResolverTest;
+use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest;
-class ControllerResolverTest extends BaseControllerResolverTest
+class ControllerResolverTest extends ContainerControllerResolverTest
{
public function testGetControllerOnContainerAware()
{
@@ -55,7 +57,7 @@ public function testGetControllerWithBundleNotation()
->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController::testAction'))
;
- $resolver = $this->createControllerResolver(null, $parser);
+ $resolver = $this->createControllerResolver(null, null, $parser);
$request = Request::create('/');
$request->attributes->set('_controller', $shortName);
@@ -66,105 +68,45 @@ public function testGetControllerWithBundleNotation()
$this->assertSame('testAction', $controller[1]);
}
- public function testGetControllerService()
+ public function testAbstractControllerGetsContainerWhenNotSet()
{
- $container = $this->createMockContainer();
- $container->expects($this->once())
- ->method('get')
- ->with('foo')
- ->will($this->returnValue($this))
- ;
-
- $resolver = $this->createControllerResolver(null, null, $container);
- $request = Request::create('/');
- $request->attributes->set('_controller', 'foo:controllerMethod1');
+ class_exists(AbstractControllerTest::class);
- $controller = $resolver->getController($request);
+ $controller = new TestAbstractController(false);
- $this->assertInstanceOf(get_class($this), $controller[0]);
- $this->assertSame('controllerMethod1', $controller[1]);
- }
+ $container = new Container();
+ $container->set(TestAbstractController::class, $controller);
- public function testGetControllerInvokableService()
- {
- $invokableController = new InvokableController('bar');
+ $resolver = $this->createControllerResolver(null, $container);
- $container = $this->createMockContainer();
- $container->expects($this->once())
- ->method('has')
- ->with('foo')
- ->will($this->returnValue(true))
- ;
- $container->expects($this->once())
- ->method('get')
- ->with('foo')
- ->will($this->returnValue($invokableController))
- ;
-
- $resolver = $this->createControllerResolver(null, null, $container);
$request = Request::create('/');
- $request->attributes->set('_controller', 'foo');
-
- $controller = $resolver->getController($request);
+ $request->attributes->set('_controller', TestAbstractController::class.'::fooAction');
- $this->assertEquals($invokableController, $controller);
+ $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request));
+ $this->assertSame($container, $controller->setContainer($container));
}
- public function testGetControllerInvokableServiceWithClassNameAsName()
+ public function testAbstractControllerGetsNoContainerWhenSet()
{
- $invokableController = new InvokableController('bar');
- $className = __NAMESPACE__.'\InvokableController';
-
- $container = $this->createMockContainer();
- $container->expects($this->once())
- ->method('has')
- ->with($className)
- ->will($this->returnValue(true))
- ;
- $container->expects($this->once())
- ->method('get')
- ->with($className)
- ->will($this->returnValue($invokableController))
- ;
-
- $resolver = $this->createControllerResolver(null, null, $container);
- $request = Request::create('/');
- $request->attributes->set('_controller', $className);
+ class_exists(AbstractControllerTest::class);
- $controller = $resolver->getController($request);
+ $controller = new TestAbstractController(false);
+ $controllerContainer = new Container();
+ $controller->setContainer($controllerContainer);
- $this->assertEquals($invokableController, $controller);
- }
+ $container = new Container();
+ $container->set(TestAbstractController::class, $controller);
- /**
- * @dataProvider getUndefinedControllers
- */
- public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null)
- {
- // All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex
- $resolver = $this->createControllerResolver();
- $this->setExpectedExceptionRegExp($exceptionName, $exceptionMessage);
+ $resolver = $this->createControllerResolver(null, $container);
$request = Request::create('/');
- $request->attributes->set('_controller', $controller);
- $resolver->getController($request);
- }
+ $request->attributes->set('_controller', TestAbstractController::class.'::fooAction');
- public function getUndefinedControllers()
- {
- return array(
- array('foo', '\LogicException', '/Unable to parse the controller name "foo"\./'),
- array('oof::bar', '\InvalidArgumentException', '/Class "oof" does not exist\./'),
- array('stdClass', '\LogicException', '/Unable to parse the controller name "stdClass"\./'),
- array(
- 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar',
- '\InvalidArgumentException',
- '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/',
- ),
- );
+ $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request));
+ $this->assertSame($controllerContainer, $controller->setContainer($container));
}
- protected function createControllerResolver(LoggerInterface $logger = null, ControllerNameParser $parser = null, ContainerInterface $container = null)
+ protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null, ControllerNameParser $parser = null)
{
if (!$parser) {
$parser = $this->createMockParser();
@@ -179,12 +121,12 @@ protected function createControllerResolver(LoggerInterface $logger = null, Cont
protected function createMockParser()
{
- return $this->getMock('Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser', array(), array(), '', false);
+ return $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser')->disableOriginalConstructor()->getMock();
}
protected function createMockContainer()
{
- return $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ return $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
}
}
@@ -210,14 +152,3 @@ public function __invoke()
{
}
}
-
-class InvokableController
-{
- public function __construct($bar) // mandatory argument to prevent automatic instantiation
- {
- }
-
- public function __invoke()
- {
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
index 2821e7faf837e..9fd20649289de 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
@@ -11,679 +11,18 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
-use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File;
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\RequestStack;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpFoundation\ResponseHeaderBag;
-use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
-use Symfony\Component\HttpFoundation\StreamedResponse;
-use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
-use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
-use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
-use Symfony\Component\Security\Core\User\User;
-use Symfony\Component\Serializer\SerializerInterface;
-class ControllerTest extends TestCase
+class ControllerTest extends ControllerTraitTest
{
- public function testForward()
+ protected function createController()
{
- $request = Request::create('/');
- $request->setLocale('fr');
- $request->setRequestFormat('xml');
-
- $requestStack = new RequestStack();
- $requestStack->push($request);
-
- $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
- $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
- return new Response($request->getRequestFormat().'--'.$request->getLocale());
- }));
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('get')->will($this->returnValue($requestStack));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($kernel));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $response = $controller->forward('a_controller');
- $this->assertEquals('xml--fr', $response->getContent());
- }
-
- public function testGetUser()
- {
- $user = new User('user', 'pass');
- $token = new UsernamePasswordToken($user, 'pass', 'default', array('ROLE_USER'));
-
- $controller = new TestController();
- $controller->setContainer($this->getContainerWithTokenStorage($token));
-
- $this->assertSame($controller->getUser(), $user);
- }
-
- public function testGetUserAnonymousUserConvertedToNull()
- {
- $token = new AnonymousToken('default', 'anon.');
-
- $controller = new TestController();
- $controller->setContainer($this->getContainerWithTokenStorage($token));
-
- $this->assertNull($controller->getUser());
- }
-
- public function testGetUserWithEmptyTokenStorage()
- {
- $controller = new TestController();
- $controller->setContainer($this->getContainerWithTokenStorage(null));
-
- $this->assertNull($controller->getUser());
- }
-
- /**
- * @expectedException \LogicException
- * @expectedExceptionMessage The SecurityBundle is not registered in your application.
- */
- public function testGetUserWithEmptyContainer()
- {
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container
- ->expects($this->once())
- ->method('has')
- ->with('security.token_storage')
- ->will($this->returnValue(false));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $controller->getUser();
- }
-
- /**
- * @param $token
- *
- * @return ContainerInterface
- */
- private function getContainerWithTokenStorage($token = null)
- {
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage');
- $tokenStorage
- ->expects($this->once())
- ->method('getToken')
- ->will($this->returnValue($token));
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container
- ->expects($this->once())
- ->method('has')
- ->with('security.token_storage')
- ->will($this->returnValue(true));
-
- $container
- ->expects($this->once())
- ->method('get')
- ->with('security.token_storage')
- ->will($this->returnValue($tokenStorage));
-
- return $container;
- }
-
- public function testJson()
- {
- $container = $this->getMock(ContainerInterface::class);
- $container
- ->expects($this->once())
- ->method('has')
- ->with('serializer')
- ->will($this->returnValue(false));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $response = $controller->json(array());
- $this->assertInstanceOf(JsonResponse::class, $response);
- $this->assertEquals('[]', $response->getContent());
- }
-
- public function testJsonWithSerializer()
- {
- $container = $this->getMock(ContainerInterface::class);
- $container
- ->expects($this->once())
- ->method('has')
- ->with('serializer')
- ->will($this->returnValue(true));
-
- $serializer = $this->getMock(SerializerInterface::class);
- $serializer
- ->expects($this->once())
- ->method('serialize')
- ->with(array(), 'json', array('json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS))
- ->will($this->returnValue('[]'));
-
- $container
- ->expects($this->once())
- ->method('get')
- ->with('serializer')
- ->will($this->returnValue($serializer));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $response = $controller->json(array());
- $this->assertInstanceOf(JsonResponse::class, $response);
- $this->assertEquals('[]', $response->getContent());
- }
-
- public function testJsonWithSerializerContextOverride()
- {
- $container = $this->getMock(ContainerInterface::class);
- $container
- ->expects($this->once())
- ->method('has')
- ->with('serializer')
- ->will($this->returnValue(true));
-
- $serializer = $this->getMock(SerializerInterface::class);
- $serializer
- ->expects($this->once())
- ->method('serialize')
- ->with(array(), 'json', array('json_encode_options' => 0, 'other' => 'context'))
- ->will($this->returnValue('[]'));
-
- $container
- ->expects($this->once())
- ->method('get')
- ->with('serializer')
- ->will($this->returnValue($serializer));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $response = $controller->json(array(), 200, array(), array('json_encode_options' => 0, 'other' => 'context'));
- $this->assertInstanceOf(JsonResponse::class, $response);
- $this->assertEquals('[]', $response->getContent());
- $response->setEncodingOptions(JSON_FORCE_OBJECT);
- $this->assertEquals('{}', $response->getContent());
- }
-
- public function testFile()
- {
- /* @var ContainerInterface $container */
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
- $container->set('kernel', $kernel);
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- /* @var BinaryFileResponse $response */
- $response = $controller->file(new File(__FILE__));
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
- $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
- }
-
- public function testFileAsInline()
- {
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $controller = new TestController();
- $controller->setContainer($container);
-
- /* @var BinaryFileResponse $response */
- $response = $controller->file(new File(__FILE__), null, ResponseHeaderBag::DISPOSITION_INLINE);
-
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_INLINE, $response->headers->get('content-disposition'));
- $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
- }
-
- public function testFileWithOwnFileName()
- {
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $controller = new TestController();
- $controller->setContainer($container);
-
- /* @var BinaryFileResponse $response */
- $fileName = 'test.php';
- $response = $controller->file(new File(__FILE__), $fileName);
-
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
- $this->assertContains($fileName, $response->headers->get('content-disposition'));
- }
-
- public function testFileWithOwnFileNameAsInline()
- {
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $controller = new TestController();
- $controller->setContainer($container);
-
- /* @var BinaryFileResponse $response */
- $fileName = 'test.php';
- $response = $controller->file(new File(__FILE__), $fileName, ResponseHeaderBag::DISPOSITION_INLINE);
-
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_INLINE, $response->headers->get('content-disposition'));
- $this->assertContains($fileName, $response->headers->get('content-disposition'));
- }
-
- public function testFileFromPath()
- {
- $controller = new TestController();
-
- /* @var BinaryFileResponse $response */
- $response = $controller->file(__FILE__);
-
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
- $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
- }
-
- public function testFileFromPathWithCustomizedFileName()
- {
- $controller = new TestController();
-
- /* @var BinaryFileResponse $response */
- $response = $controller->file(__FILE__, 'test.php');
-
- $this->assertInstanceOf(BinaryFileResponse::class, $response);
- $this->assertSame(200, $response->getStatusCode());
- if ($response->headers->get('content-type')) {
- $this->assertSame('text/x-php', $response->headers->get('content-type'));
- }
- $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
- $this->assertContains('test.php', $response->headers->get('content-disposition'));
- }
-
- /**
- * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException
- */
- public function testFileWhichDoesNotExist()
- {
- $controller = new TestController();
-
- /* @var BinaryFileResponse $response */
- $response = $controller->file('some-file.txt', 'test.php');
- }
-
- public function testIsGranted()
- {
- $authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
- $authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($authorizationChecker));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertTrue($controller->isGranted('foo'));
- }
-
- /**
- * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
- */
- public function testdenyAccessUnlessGranted()
- {
- $authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
- $authorizationChecker->expects($this->once())->method('isGranted')->willReturn(false);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($authorizationChecker));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $controller->denyAccessUnlessGranted('foo');
- }
-
- public function testRenderViewTwig()
- {
- $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
- $twig->expects($this->once())->method('render')->willReturn('bar');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(false));
- $container->expects($this->at(1))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(2))->method('get')->will($this->returnValue($twig));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals('bar', $controller->renderView('foo'));
- }
-
- public function testRenderTwig()
- {
- $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
- $twig->expects($this->once())->method('render')->willReturn('bar');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(false));
- $container->expects($this->at(1))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(2))->method('get')->will($this->returnValue($twig));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals('bar', $controller->render('foo')->getContent());
- }
-
- public function testStreamTwig()
- {
- $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(false));
- $container->expects($this->at(1))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(2))->method('get')->will($this->returnValue($twig));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $controller->stream('foo'));
- }
-
- public function testRedirectToRoute()
- {
- $router = $this->getMock('Symfony\Component\Routing\RouterInterface');
- $router->expects($this->once())->method('generate')->willReturn('/foo');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('get')->will($this->returnValue($router));
-
- $controller = new TestController();
- $controller->setContainer($container);
- $response = $controller->redirectToRoute('foo');
-
- $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
- $this->assertSame('/foo', $response->getTargetUrl());
- $this->assertSame(302, $response->getStatusCode());
- }
-
- public function testAddFlash()
- {
- $flashBag = new FlashBag();
- $session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session');
- $session->expects($this->once())->method('getFlashBag')->willReturn($flashBag);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($session));
-
- $controller = new TestController();
- $controller->setContainer($container);
- $controller->addFlash('foo', 'bar');
-
- $this->assertSame(array('bar'), $flashBag->get('foo'));
- }
-
- public function testCreateAccessDeniedException()
- {
- $controller = new TestController();
-
- $this->assertInstanceOf('Symfony\Component\Security\Core\Exception\AccessDeniedException', $controller->createAccessDeniedException());
- }
-
- public function testIsCsrfTokenValid()
- {
- $tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');
- $tokenManager->expects($this->once())->method('isTokenValid')->willReturn(true);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($tokenManager));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertTrue($controller->isCsrfTokenValid('foo', 'bar'));
- }
-
- public function testGenerateUrl()
- {
- $router = $this->getMock('Symfony\Component\Routing\RouterInterface');
- $router->expects($this->once())->method('generate')->willReturn('/foo');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('get')->will($this->returnValue($router));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals('/foo', $controller->generateUrl('foo'));
- }
-
- public function testRedirect()
- {
- $controller = new TestController();
- $response = $controller->redirect('http://dunglas.fr', 301);
-
- $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
- $this->assertSame('http://dunglas.fr', $response->getTargetUrl());
- $this->assertSame(301, $response->getStatusCode());
- }
-
- public function testRenderViewTemplating()
- {
- $templating = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface');
- $templating->expects($this->once())->method('render')->willReturn('bar');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->willReturn(true);
- $container->expects($this->at(1))->method('get')->will($this->returnValue($templating));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals('bar', $controller->renderView('foo'));
- }
-
- public function testRenderTemplating()
- {
- $templating = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface');
- $templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->willReturn(true);
- $container->expects($this->at(1))->method('get')->will($this->returnValue($templating));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals('bar', $controller->render('foo')->getContent());
- }
-
- public function testStreamTemplating()
- {
- $templating = $this->getMock('Symfony\Component\Routing\RouterInterface');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->willReturn(true);
- $container->expects($this->at(1))->method('get')->will($this->returnValue($templating));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $controller->stream('foo'));
- }
-
- public function testCreateNotFoundException()
- {
- $controller = new TestController();
-
- $this->assertInstanceOf('Symfony\Component\HttpKernel\Exception\NotFoundHttpException', $controller->createNotFoundException());
- }
-
- public function testCreateForm()
- {
- $form = $this->getMock('Symfony\Component\Form\FormInterface');
-
- $formFactory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
- $formFactory->expects($this->once())->method('create')->willReturn($form);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('get')->will($this->returnValue($formFactory));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals($form, $controller->createForm('foo'));
- }
-
- public function testCreateFormBuilder()
- {
- $formBuilder = $this->getMock('Symfony\Component\Form\FormBuilderInterface');
-
- $formFactory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
- $formFactory->expects($this->once())->method('createBuilder')->willReturn($formBuilder);
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('get')->will($this->returnValue($formFactory));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals($formBuilder, $controller->createFormBuilder('foo'));
- }
-
- public function testGetDoctrine()
- {
- $doctrine = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container->expects($this->at(0))->method('has')->will($this->returnValue(true));
- $container->expects($this->at(1))->method('get')->will($this->returnValue($doctrine));
-
- $controller = new TestController();
- $controller->setContainer($container);
-
- $this->assertEquals($doctrine, $controller->getDoctrine());
+ return new TestController();
}
}
class TestController extends Controller
{
- public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
- {
- return parent::generateUrl($route, $parameters, $referenceType);
- }
-
- public function redirect($url, $status = 302)
- {
- return parent::redirect($url, $status);
- }
-
- public function forward($controller, array $path = array(), array $query = array())
- {
- return parent::forward($controller, $path, $query);
- }
-
- public function getUser()
- {
- return parent::getUser();
- }
-
- public function json($data, $status = 200, $headers = array(), $context = array())
- {
- return parent::json($data, $status, $headers, $context);
- }
-
- public function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
- {
- return parent::file($file, $fileName, $disposition);
- }
-
- public function isGranted($attributes, $object = null)
- {
- return parent::isGranted($attributes, $object);
- }
-
- public function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
- {
- parent::denyAccessUnlessGranted($attributes, $object, $message);
- }
-
- public function redirectToRoute($route, array $parameters = array(), $status = 302)
- {
- return parent::redirectToRoute($route, $parameters, $status);
- }
-
- public function addFlash($type, $message)
- {
- parent::addFlash($type, $message);
- }
-
- public function isCsrfTokenValid($id, $token)
- {
- return parent::isCsrfTokenValid($id, $token);
- }
-
- public function renderView($view, array $parameters = array())
- {
- return parent::renderView($view, $parameters);
- }
-
- public function render($view, array $parameters = array(), Response $response = null)
- {
- return parent::render($view, $parameters, $response);
- }
-
- public function stream($view, array $parameters = array(), StreamedResponse $response = null)
- {
- return parent::stream($view, $parameters, $response);
- }
-
- public function createNotFoundException($message = 'Not Found', \Exception $previous = null)
- {
- return parent::createNotFoundException($message, $previous);
- }
-
- public function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null)
- {
- return parent::createAccessDeniedException($message, $previous);
- }
-
- public function createForm($type, $data = null, array $options = array())
- {
- return parent::createForm($type, $data, $options);
- }
-
- public function createFormBuilder($data = null, array $options = array())
- {
- return parent::createFormBuilder($data, $options);
- }
-
- public function getDoctrine()
- {
- return parent::getDoctrine();
- }
+ use TestControllerTrait;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php
new file mode 100644
index 0000000000000..2bd18aa441451
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php
@@ -0,0 +1,627 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\File\File;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
+use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
+use Symfony\Component\Security\Core\User\User;
+use Symfony\Component\Serializer\SerializerInterface;
+
+abstract class ControllerTraitTest extends TestCase
+{
+ abstract protected function createController();
+
+ public function testForward()
+ {
+ $request = Request::create('/');
+ $request->setLocale('fr');
+ $request->setRequestFormat('xml');
+
+ $requestStack = new RequestStack();
+ $requestStack->push($request);
+
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
+ return new Response($request->getRequestFormat().'--'.$request->getLocale());
+ }));
+
+ $container = new Container();
+ $container->set('request_stack', $requestStack);
+ $container->set('http_kernel', $kernel);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $response = $controller->forward('a_controller');
+ $this->assertEquals('xml--fr', $response->getContent());
+ }
+
+ public function testGetUser()
+ {
+ $user = new User('user', 'pass');
+ $token = new UsernamePasswordToken($user, 'pass', 'default', array('ROLE_USER'));
+
+ $controller = $this->createController();
+ $controller->setContainer($this->getContainerWithTokenStorage($token));
+
+ $this->assertSame($controller->getUser(), $user);
+ }
+
+ public function testGetUserAnonymousUserConvertedToNull()
+ {
+ $token = new AnonymousToken('default', 'anon.');
+
+ $controller = $this->createController();
+ $controller->setContainer($this->getContainerWithTokenStorage($token));
+
+ $this->assertNull($controller->getUser());
+ }
+
+ public function testGetUserWithEmptyTokenStorage()
+ {
+ $controller = $this->createController();
+ $controller->setContainer($this->getContainerWithTokenStorage(null));
+
+ $this->assertNull($controller->getUser());
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage The SecurityBundle is not registered in your application.
+ */
+ public function testGetUserWithEmptyContainer()
+ {
+ $controller = $this->createController();
+ $controller->setContainer(new Container());
+
+ $controller->getUser();
+ }
+
+ /**
+ * @param $token
+ *
+ * @return Container
+ */
+ private function getContainerWithTokenStorage($token = null)
+ {
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage')->getMock();
+ $tokenStorage
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue($token));
+
+ $container = new Container();
+ $container->set('security.token_storage', $tokenStorage);
+
+ return $container;
+ }
+
+ public function testJson()
+ {
+ $controller = $this->createController();
+ $controller->setContainer(new Container());
+
+ $response = $controller->json(array());
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertEquals('[]', $response->getContent());
+ }
+
+ public function testJsonWithSerializer()
+ {
+ $container = new Container();
+
+ $serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
+ $serializer
+ ->expects($this->once())
+ ->method('serialize')
+ ->with(array(), 'json', array('json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS))
+ ->will($this->returnValue('[]'));
+
+ $container->set('serializer', $serializer);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $response = $controller->json(array());
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertEquals('[]', $response->getContent());
+ }
+
+ public function testJsonWithSerializerContextOverride()
+ {
+ $container = new Container();
+
+ $serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
+ $serializer
+ ->expects($this->once())
+ ->method('serialize')
+ ->with(array(), 'json', array('json_encode_options' => 0, 'other' => 'context'))
+ ->will($this->returnValue('[]'));
+
+ $container->set('serializer', $serializer);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $response = $controller->json(array(), 200, array(), array('json_encode_options' => 0, 'other' => 'context'));
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertEquals('[]', $response->getContent());
+ $response->setEncodingOptions(JSON_FORCE_OBJECT);
+ $this->assertEquals('{}', $response->getContent());
+ }
+
+ public function testFile()
+ {
+ $container = new Container();
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $container->set('http_kernel', $kernel);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ /* @var BinaryFileResponse $response */
+ $response = $controller->file(new File(__FILE__));
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
+ $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
+ }
+
+ public function testFileAsInline()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $response = $controller->file(new File(__FILE__), null, ResponseHeaderBag::DISPOSITION_INLINE);
+
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_INLINE, $response->headers->get('content-disposition'));
+ $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
+ }
+
+ public function testFileWithOwnFileName()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $fileName = 'test.php';
+ $response = $controller->file(new File(__FILE__), $fileName);
+
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
+ $this->assertContains($fileName, $response->headers->get('content-disposition'));
+ }
+
+ public function testFileWithOwnFileNameAsInline()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $fileName = 'test.php';
+ $response = $controller->file(new File(__FILE__), $fileName, ResponseHeaderBag::DISPOSITION_INLINE);
+
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_INLINE, $response->headers->get('content-disposition'));
+ $this->assertContains($fileName, $response->headers->get('content-disposition'));
+ }
+
+ public function testFileFromPath()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $response = $controller->file(__FILE__);
+
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
+ $this->assertContains(basename(__FILE__), $response->headers->get('content-disposition'));
+ }
+
+ public function testFileFromPathWithCustomizedFileName()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $response = $controller->file(__FILE__, 'test.php');
+
+ $this->assertInstanceOf(BinaryFileResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ if ($response->headers->get('content-type')) {
+ $this->assertSame('text/x-php', $response->headers->get('content-type'));
+ }
+ $this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition'));
+ $this->assertContains('test.php', $response->headers->get('content-disposition'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException
+ */
+ public function testFileWhichDoesNotExist()
+ {
+ $controller = $this->createController();
+
+ /* @var BinaryFileResponse $response */
+ $response = $controller->file('some-file.txt', 'test.php');
+ }
+
+ public function testIsGranted()
+ {
+ $authorizationChecker = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
+ $authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
+
+ $container = new Container();
+ $container->set('security.authorization_checker', $authorizationChecker);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertTrue($controller->isGranted('foo'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
+ */
+ public function testdenyAccessUnlessGranted()
+ {
+ $authorizationChecker = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
+ $authorizationChecker->expects($this->once())->method('isGranted')->willReturn(false);
+
+ $container = new Container();
+ $container->set('security.authorization_checker', $authorizationChecker);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $controller->denyAccessUnlessGranted('foo');
+ }
+
+ public function testRenderViewTwig()
+ {
+ $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
+ $twig->expects($this->once())->method('render')->willReturn('bar');
+
+ $container = new Container();
+ $container->set('twig', $twig);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->renderView('foo'));
+ }
+
+ public function testRenderTwig()
+ {
+ $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
+ $twig->expects($this->once())->method('render')->willReturn('bar');
+
+ $container = new Container();
+ $container->set('twig', $twig);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->render('foo')->getContent());
+ }
+
+ public function testStreamTwig()
+ {
+ $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
+
+ $container = new Container();
+ $container->set('twig', $twig);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $controller->stream('foo'));
+ }
+
+ public function testRedirectToRoute()
+ {
+ $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
+ $router->expects($this->once())->method('generate')->willReturn('/foo');
+
+ $container = new Container();
+ $container->set('router', $router);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+ $response = $controller->redirectToRoute('foo');
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
+ $this->assertSame('/foo', $response->getTargetUrl());
+ $this->assertSame(302, $response->getStatusCode());
+ }
+
+ public function testAddFlash()
+ {
+ $flashBag = new FlashBag();
+ $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock();
+ $session->expects($this->once())->method('getFlashBag')->willReturn($flashBag);
+
+ $container = new Container();
+ $container->set('session', $session);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+ $controller->addFlash('foo', 'bar');
+
+ $this->assertSame(array('bar'), $flashBag->get('foo'));
+ }
+
+ public function testCreateAccessDeniedException()
+ {
+ $controller = $this->createController();
+
+ $this->assertInstanceOf('Symfony\Component\Security\Core\Exception\AccessDeniedException', $controller->createAccessDeniedException());
+ }
+
+ public function testIsCsrfTokenValid()
+ {
+ $tokenManager = $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock();
+ $tokenManager->expects($this->once())->method('isTokenValid')->willReturn(true);
+
+ $container = new Container();
+ $container->set('security.csrf.token_manager', $tokenManager);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertTrue($controller->isCsrfTokenValid('foo', 'bar'));
+ }
+
+ public function testGenerateUrl()
+ {
+ $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
+ $router->expects($this->once())->method('generate')->willReturn('/foo');
+
+ $container = new Container();
+ $container->set('router', $router);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('/foo', $controller->generateUrl('foo'));
+ }
+
+ public function testRedirect()
+ {
+ $controller = $this->createController();
+ $response = $controller->redirect('http://dunglas.fr', 301);
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
+ $this->assertSame('http://dunglas.fr', $response->getTargetUrl());
+ $this->assertSame(301, $response->getStatusCode());
+ }
+
+ public function testRenderViewTemplating()
+ {
+ $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
+ $templating->expects($this->once())->method('render')->willReturn('bar');
+
+ $container = new Container();
+ $container->set('templating', $templating);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->renderView('foo'));
+ }
+
+ public function testRenderTemplating()
+ {
+ $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
+ $templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
+
+ $container = new Container();
+ $container->set('templating', $templating);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->render('foo')->getContent());
+ }
+
+ public function testStreamTemplating()
+ {
+ $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
+
+ $container = new Container();
+ $container->set('templating', $templating);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $controller->stream('foo'));
+ }
+
+ public function testCreateNotFoundException()
+ {
+ $controller = $this->createController();
+
+ $this->assertInstanceOf('Symfony\Component\HttpKernel\Exception\NotFoundHttpException', $controller->createNotFoundException());
+ }
+
+ public function testCreateForm()
+ {
+ $form = $this->getMockBuilder('Symfony\Component\Form\FormInterface')->getMock();
+
+ $formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
+ $formFactory->expects($this->once())->method('create')->willReturn($form);
+
+ $container = new Container();
+ $container->set('form.factory', $formFactory);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals($form, $controller->createForm('foo'));
+ }
+
+ public function testCreateFormBuilder()
+ {
+ $formBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilderInterface')->getMock();
+
+ $formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
+ $formFactory->expects($this->once())->method('createBuilder')->willReturn($formBuilder);
+
+ $container = new Container();
+ $container->set('form.factory', $formFactory);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals($formBuilder, $controller->createFormBuilder('foo'));
+ }
+
+ public function testGetDoctrine()
+ {
+ $doctrine = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock();
+
+ $container = new Container();
+ $container->set('doctrine', $doctrine);
+
+ $controller = $this->createController();
+ $controller->setContainer($container);
+
+ $this->assertEquals($doctrine, $controller->getDoctrine());
+ }
+}
+
+trait TestControllerTrait
+{
+ public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
+ {
+ return parent::generateUrl($route, $parameters, $referenceType);
+ }
+
+ public function redirect($url, $status = 302)
+ {
+ return parent::redirect($url, $status);
+ }
+
+ public function forward($controller, array $path = array(), array $query = array())
+ {
+ return parent::forward($controller, $path, $query);
+ }
+
+ public function getUser()
+ {
+ return parent::getUser();
+ }
+
+ public function json($data, $status = 200, $headers = array(), $context = array())
+ {
+ return parent::json($data, $status, $headers, $context);
+ }
+
+ public function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
+ {
+ return parent::file($file, $fileName, $disposition);
+ }
+
+ public function isGranted($attributes, $object = null)
+ {
+ return parent::isGranted($attributes, $object);
+ }
+
+ public function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
+ {
+ parent::denyAccessUnlessGranted($attributes, $object, $message);
+ }
+
+ public function redirectToRoute($route, array $parameters = array(), $status = 302)
+ {
+ return parent::redirectToRoute($route, $parameters, $status);
+ }
+
+ public function addFlash($type, $message)
+ {
+ parent::addFlash($type, $message);
+ }
+
+ public function isCsrfTokenValid($id, $token)
+ {
+ return parent::isCsrfTokenValid($id, $token);
+ }
+
+ public function renderView($view, array $parameters = array())
+ {
+ return parent::renderView($view, $parameters);
+ }
+
+ public function render($view, array $parameters = array(), Response $response = null)
+ {
+ return parent::render($view, $parameters, $response);
+ }
+
+ public function stream($view, array $parameters = array(), StreamedResponse $response = null)
+ {
+ return parent::stream($view, $parameters, $response);
+ }
+
+ public function createNotFoundException($message = 'Not Found', \Exception $previous = null)
+ {
+ return parent::createNotFoundException($message, $previous);
+ }
+
+ public function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null)
+ {
+ return parent::createAccessDeniedException($message, $previous);
+ }
+
+ public function createForm($type, $data = null, array $options = array())
+ {
+ return parent::createForm($type, $data, $options);
+ }
+
+ public function createFormBuilder($data = null, array $options = array())
+ {
+ return parent::createFormBuilder($data, $options);
+ }
+
+ public function getDoctrine()
+ {
+ return parent::getDoctrine();
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php
index eaca189330599..14b6e4428e550 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php
@@ -66,14 +66,14 @@ public function testRoute($permanent, $ignoreAttributes, $expectedCode, $expecte
$request->attributes = new ParameterBag($attributes);
- $router = $this->getMock('Symfony\Component\Routing\RouterInterface');
+ $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router
->expects($this->once())
->method('generate')
->with($this->equalTo($route), $this->equalTo($expectedAttributes))
->will($this->returnValue($url));
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
@@ -230,7 +230,7 @@ public function testPathQueryParams($expectedUrl, $path, $queryString)
private function createRequestObject($scheme, $host, $port, $baseUrl, $queryString = '')
{
- $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
+ $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
$request
->expects($this->any())
->method('getScheme')
@@ -257,7 +257,7 @@ private function createRequestObject($scheme, $host, $port, $baseUrl, $queryStri
private function createRedirectController($httpPort = null, $httpsPort = null)
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
if (null !== $httpPort) {
$container
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php
new file mode 100644
index 0000000000000..04e6447ee93ea
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php
@@ -0,0 +1,69 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
+use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * @author Kévin Dunglas
+ */
+class TemplateControllerTest extends TestCase
+{
+ public function testTwig()
+ {
+ $twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
+ $twig->expects($this->once())->method('render')->willReturn('bar');
+
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
+ $container->expects($this->at(0))->method('has')->will($this->returnValue(false));
+ $container->expects($this->at(1))->method('has')->will($this->returnValue(true));
+ $container->expects($this->at(2))->method('get')->will($this->returnValue($twig));
+
+ $controller = new TemplateController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent());
+ }
+
+ public function testTemplating()
+ {
+ $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
+ $templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
+
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
+ $container->expects($this->at(0))->method('has')->willReturn(true);
+ $container->expects($this->at(1))->method('get')->will($this->returnValue($templating));
+
+ $controller = new TemplateController();
+ $controller->setContainer($container);
+
+ $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent());
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage You can not use the TemplateController if the Templating Component or the Twig Bundle are not available.
+ */
+ public function testNoTwigNorTemplating()
+ {
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
+ $container->expects($this->at(0))->method('has')->willReturn(false);
+ $container->expects($this->at(1))->method('has')->willReturn(false);
+
+ $controller = new TemplateController();
+ $controller->setContainer($container);
+
+ $controller->templateAction('mytemplate')->getContent();
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php
index 204fdf09b653e..3516aa93608fc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php
@@ -11,56 +11,37 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass;
-class AddCacheWarmerPassTest extends \PHPUnit_Framework_TestCase
+class AddCacheWarmerPassTest extends TestCase
{
public function testThatCacheWarmersAreProcessedInPriorityOrder()
{
- $services = array(
- 'my_cache_warmer_service1' => array(0 => array('priority' => 100)),
- 'my_cache_warmer_service2' => array(0 => array('priority' => 200)),
- 'my_cache_warmer_service3' => array(0 => array()),
- );
-
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
- );
-
- $container->expects($this->atLeastOnce())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue($services));
- $container->expects($this->atLeastOnce())
- ->method('getDefinition')
- ->with('cache_warmer')
- ->will($this->returnValue($definition));
- $container->expects($this->atLeastOnce())
- ->method('hasDefinition')
- ->with('cache_warmer')
- ->will($this->returnValue(true));
+ $container = new ContainerBuilder();
- $definition->expects($this->once())
- ->method('replaceArgument')
- ->with(0, array(
- new Reference('my_cache_warmer_service2'),
- new Reference('my_cache_warmer_service1'),
- new Reference('my_cache_warmer_service3'),
- ));
+ $definition = $container->register('cache_warmer')->addArgument(null);
+ $container->register('my_cache_warmer_service1')->addTag('kernel.cache_warmer', array('priority' => 100));
+ $container->register('my_cache_warmer_service2')->addTag('kernel.cache_warmer', array('priority' => 200));
+ $container->register('my_cache_warmer_service3')->addTag('kernel.cache_warmer');
$addCacheWarmerPass = new AddCacheWarmerPass();
$addCacheWarmerPass->process($container);
+
+ $expected = array(
+ new Reference('my_cache_warmer_service2'),
+ new Reference('my_cache_warmer_service1'),
+ new Reference('my_cache_warmer_service3'),
+ );
+ $this->assertEquals($expected, $definition->getArgument(0));
}
public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
- );
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();
$container->expects($this->never())->method('findTaggedServiceIds');
$container->expects($this->never())->method('getDefinition');
@@ -76,11 +57,8 @@ public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition()
public function testThatCacheWarmersMightBeNotDefined()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
- );
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php
index ab0bc985703ad..58a0da41c3d91 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php
@@ -11,13 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\Bundle\Bundle;
-class AddConsoleCommandPassTest extends \PHPUnit_Framework_TestCase
+/**
+ * @group legacy
+ */
+class AddConsoleCommandPassTest extends TestCase
{
/**
* @dataProvider visibilityProvider
@@ -36,18 +40,20 @@ public function testProcess($public)
$container->compile();
$alias = 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand';
- if ($container->hasAlias($alias)) {
- $this->assertSame('my-command', (string) $container->getAlias($alias));
+
+ if ($public) {
+ $this->assertFalse($container->hasAlias($alias));
+ $id = 'my-command';
} else {
+ $id = $alias;
// The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass
// in case the original service is private
$this->assertFalse($container->hasDefinition('my-command'));
$this->assertTrue($container->hasDefinition($alias));
}
- $id = $public ? 'my-command' : 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand';
$this->assertTrue($container->hasParameter('console.command.ids'));
- $this->assertSame(array($id), $container->getParameter('console.command.ids'));
+ $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids'));
}
public function visibilityProvider()
@@ -90,6 +96,28 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand()
$container->compile();
}
+
+ public function testProcessPrivateServicesWithSameCommand()
+ {
+ $container = new ContainerBuilder();
+ $className = 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand';
+
+ $definition1 = new Definition($className);
+ $definition1->addTag('console.command')->setPublic(false);
+
+ $definition2 = new Definition($className);
+ $definition2->addTag('console.command')->setPublic(false);
+
+ $container->setDefinition('my-command1', $definition1);
+ $container->setDefinition('my-command2', $definition2);
+
+ (new AddConsoleCommandPass())->process($container);
+
+ $alias1 = 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand';
+ $alias2 = $alias1.'_my-command2';
+ $this->assertTrue($container->hasAlias($alias1));
+ $this->assertTrue($container->hasAlias($alias2));
+ }
}
class MyCommand extends Command
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
index 0629d1ebafd1f..d9065e46d5693 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
@@ -9,57 +9,56 @@
* 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\AddConstraintValidatorsPass;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
-class AddConstraintValidatorsPassTest extends \PHPUnit_Framework_TestCase
+/**
+ * @group legacy
+ */
+class AddConstraintValidatorsPassTest extends TestCase
{
public function testThatConstraintValidatorServicesAreProcessed()
{
- $services = array(
- 'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')),
- 'my_constraint_validator_service2' => array(),
- );
-
- $validatorFactoryDefinition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
- );
+ $container = new ContainerBuilder();
+ $validatorFactory = $container->register('validator.validator_factory')
+ ->addArgument(array());
- $validatorDefinition1 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass'));
- $validatorDefinition2 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass'));
+ $container->register('my_constraint_validator_service1', Validator1::class)
+ ->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1'));
+ $container->register('my_constraint_validator_service2', Validator2::class)
+ ->addTag('validator.constraint_validator');
- $validatorDefinition1->expects($this->atLeastOnce())
- ->method('getClass')
- ->willReturn('My\Fully\Qualified\Class\Named\Validator1');
- $validatorDefinition2->expects($this->atLeastOnce())
- ->method('getClass')
- ->willReturn('My\Fully\Qualified\Class\Named\Validator2');
+ $addConstraintValidatorsPass = new AddConstraintValidatorsPass();
+ $addConstraintValidatorsPass->process($container);
- $container->expects($this->any())
- ->method('getDefinition')
- ->with($this->anything())
- ->will($this->returnValueMap(array(
- array('my_constraint_validator_service1', $validatorDefinition1),
- array('my_constraint_validator_service2', $validatorDefinition2),
- array('validator.validator_factory', $validatorFactoryDefinition),
- )));
+ $expected = (new Definition(ServiceLocator::class, array(array(
+ Validator1::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
+ 'my_constraint_validator_alias1' => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
+ Validator2::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service2')),
+ ))))->addTag('container.service_locator')->setPublic(false);
+ $this->assertEquals($expected, $container->getDefinition((string) $validatorFactory->getArgument(0)));
+ }
- $container->expects($this->atLeastOnce())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue($services));
- $container->expects($this->atLeastOnce())
- ->method('hasDefinition')
- ->with('validator.validator_factory')
- ->will($this->returnValue(true));
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage The service "my_abstract_constraint_validator" tagged "validator.constraint_validator" must not be abstract.
+ */
+ public function testAbstractConstraintValidator()
+ {
+ $container = new ContainerBuilder();
+ $validatorFactory = $container->register('validator.validator_factory')
+ ->addArgument(array());
- $validatorFactoryDefinition->expects($this->once())
- ->method('replaceArgument')
- ->with(1, array(
- 'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1',
- 'my_constraint_validator_alias1' => 'my_constraint_validator_service1',
- 'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2',
- ));
+ $container->register('my_abstract_constraint_validator')
+ ->setAbstract(true)
+ ->addTag('validator.constraint_validator');
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
$addConstraintValidatorsPass->process($container);
@@ -67,11 +66,8 @@ public function testThatConstraintValidatorServicesAreProcessed()
public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
- );
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();
$container->expects($this->never())->method('findTaggedServiceIds');
$container->expects($this->never())->method('getDefinition');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php
index 9bc4acb9c1567..0934fe31c0c40 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
-class AddExpressionLanguageProvidersPassTest extends \PHPUnit_Framework_TestCase
+class AddExpressionLanguageProvidersPassTest extends TestCase
{
public function testProcessForRouter()
{
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolClearerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolClearerPassTest.php
index 38a2d38761e3b..9230405d7560e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolClearerPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolClearerPassTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass;
@@ -18,8 +19,9 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
-class CachePoolClearerPassTest extends \PHPUnit_Framework_TestCase
+class CachePoolClearerPassTest extends TestCase
{
public function testPoolRefsAreWeak()
{
@@ -29,6 +31,9 @@ public function testPoolRefsAreWeak()
$container->setParameter('kernel.environment', 'prod');
$container->setParameter('kernel.root_dir', 'foo');
+ $globalClearer = new Definition(Psr6CacheClearer::class);
+ $container->setDefinition('cache.global_clearer', $globalClearer);
+
$publicPool = new Definition();
$publicPool->addArgument('namespace');
$publicPool->addTag('cache.pool', array('clearer' => 'clearer_alias'));
@@ -50,6 +55,7 @@ public function testPoolRefsAreWeak()
$pass->process($container);
}
- $this->assertEquals(array(array('addPool', array(new Reference('public.pool')))), $clearer->getMethodCalls());
+ $this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $clearer->getArguments());
+ $this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $globalClearer->getArguments());
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
index 192e1493d0c38..713cd4eaca842 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;
-class CachePoolPassTest extends \PHPUnit_Framework_TestCase
+class CachePoolPassTest extends TestCase
{
private $cachePoolPass;
@@ -38,14 +39,14 @@ public function testNamespaceArgumentIsReplaced()
$adapter->addTag('cache.pool');
$container->setDefinition('app.cache_adapter', $adapter);
$container->setAlias('app.cache_adapter_alias', 'app.cache_adapter');
- $cachePool = new DefinitionDecorator('app.cache_adapter_alias');
+ $cachePool = new ChildDefinition('app.cache_adapter_alias');
$cachePool->addArgument(null);
$cachePool->addTag('cache.pool');
$container->setDefinition('app.cache_pool', $cachePool);
$this->cachePoolPass->process($container);
- $this->assertSame('C42Pcl9VBJ', $cachePool->getArgument(0));
+ $this->assertSame('D07rhFx97S', $cachePool->getArgument(0));
}
public function testArgsAreReplaced()
@@ -69,7 +70,7 @@ public function testArgsAreReplaced()
$this->assertInstanceOf(Reference::class, $cachePool->getArgument(0));
$this->assertSame('foobar', (string) $cachePool->getArgument(0));
- $this->assertSame('KO3xHaFEZU', $cachePool->getArgument(1));
+ $this->assertSame('itantF+pIq', $cachePool->getArgument(1));
$this->assertSame(3, $cachePool->getArgument(2));
}
@@ -88,7 +89,7 @@ public function testThrowsExceptionWhenCachePoolTagHasUnknownAttributes()
$adapter->setAbstract(true);
$adapter->addTag('cache.pool');
$container->setDefinition('app.cache_adapter', $adapter);
- $cachePool = new DefinitionDecorator('app.cache_adapter');
+ $cachePool = new ChildDefinition('app.cache_adapter');
$cachePool->addTag('cache.pool', array('foobar' => 123));
$container->setDefinition('app.cache_pool', $cachePool);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php
index 48c753b6e2d45..e2348972d09c7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php
@@ -11,51 +11,40 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass;
-class ConfigCachePassTest extends \PHPUnit_Framework_TestCase
+/**
+ * @group legacy
+ */
+class ConfigCachePassTest extends TestCase
{
public function testThatCheckersAreProcessedInPriorityOrder()
{
- $services = array(
- 'checker_2' => array(0 => array('priority' => 100)),
- 'checker_1' => array(0 => array('priority' => 200)),
- 'checker_3' => array(0 => array()),
- );
+ $container = new ContainerBuilder();
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
- );
-
- $container->expects($this->atLeastOnce())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue($services));
- $container->expects($this->atLeastOnce())
- ->method('getDefinition')
- ->with('config_cache_factory')
- ->will($this->returnValue($definition));
-
- $definition->expects($this->once())
- ->method('replaceArgument')
- ->with(0, array(
- new Reference('checker_1'),
- new Reference('checker_2'),
- new Reference('checker_3'),
- ));
+ $definition = $container->register('config_cache_factory')->addArgument(null);
+ $container->register('checker_2')->addTag('config_cache.resource_checker', array('priority' => 100));
+ $container->register('checker_1')->addTag('config_cache.resource_checker', array('priority' => 200));
+ $container->register('checker_3')->addTag('config_cache.resource_checker');
$pass = new ConfigCachePass();
$pass->process($container);
+
+ $expected = new IteratorArgument(array(
+ new Reference('checker_1'),
+ new Reference('checker_2'),
+ new Reference('checker_3'),
+ ));
+ $this->assertEquals($expected, $definition->getArgument(0));
}
public function testThatCheckersCanBeMissing()
{
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('findTaggedServiceIds')
- );
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock();
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php
index 5afcb4bb51994..1adfdf2734f0c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php
@@ -11,13 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
-class ControllerArgumentValueResolverPassTest extends \PHPUnit_Framework_TestCase
+/**
+ * @group legacy
+ */
+class ControllerArgumentValueResolverPassTest extends TestCase
{
public function testServicesAreOrderedAccordingToPriority()
{
@@ -42,7 +46,7 @@ public function testServicesAreOrderedAccordingToPriority()
}
(new ControllerArgumentValueResolverPass())->process($container);
- $this->assertEquals($expected, $definition->getArgument(1));
+ $this->assertEquals($expected, $definition->getArgument(1)->getValues());
}
public function testReturningEmptyArrayWhenNoService()
@@ -52,7 +56,7 @@ public function testReturningEmptyArrayWhenNoService()
$container->setDefinition('argument_resolver', $definition);
(new ControllerArgumentValueResolverPass())->process($container);
- $this->assertEquals(array(), $definition->getArgument(1));
+ $this->assertEquals(array(), $definition->getArgument(1)->getValues());
}
public function testNoArgumentResolver()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php
new file mode 100644
index 0000000000000..2d6e8ca3be478
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/DataCollectorTranslatorPassTest.php
@@ -0,0 +1,126 @@
+
+ *
+ * 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\DataCollectorTranslatorPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\Translation\TranslatorInterface;
+
+class DataCollectorTranslatorPassTest extends TestCase
+{
+ private $container;
+ private $dataCollectorTranslatorPass;
+
+ protected function setUp()
+ {
+ $this->container = new ContainerBuilder();
+ $this->dataCollectorTranslatorPass = new DataCollectorTranslatorPass();
+
+ $this->container->setParameter('translator_implementing_bag', 'Symfony\Component\Translation\Translator');
+ $this->container->setParameter('translator_not_implementing_bag', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TranslatorWithTranslatorBag');
+
+ $this->container->register('translator.data_collector', 'Symfony\Component\Translation\DataCollectorTranslator')
+ ->setPublic(false)
+ ->setDecoratedService('translator')
+ ->setArguments(array(new Reference('translator.data_collector.inner')))
+ ;
+
+ $this->container->register('data_collector.translation', 'Symfony\Component\Translation\DataCollector\TranslationDataCollector')
+ ->setArguments(array(new Reference('translator.data_collector')))
+ ;
+ }
+
+ /**
+ * @dataProvider getImplementingTranslatorBagInterfaceTranslatorClassNames
+ */
+ public function testProcessKeepsDataCollectorTranslatorIfItImplementsTranslatorBagInterface($class)
+ {
+ $this->container->register('translator', $class);
+
+ $this->dataCollectorTranslatorPass->process($this->container);
+
+ $this->assertTrue($this->container->hasDefinition('translator.data_collector'));
+ }
+
+ /**
+ * @dataProvider getImplementingTranslatorBagInterfaceTranslatorClassNames
+ */
+ public function testProcessKeepsDataCollectorIfTranslatorImplementsTranslatorBagInterface($class)
+ {
+ $this->container->register('translator', $class);
+
+ $this->dataCollectorTranslatorPass->process($this->container);
+
+ $this->assertTrue($this->container->hasDefinition('data_collector.translation'));
+ }
+
+ public function getImplementingTranslatorBagInterfaceTranslatorClassNames()
+ {
+ return array(
+ array('Symfony\Component\Translation\Translator'),
+ array('%translator_implementing_bag%'),
+ );
+ }
+
+ /**
+ * @dataProvider getNotImplementingTranslatorBagInterfaceTranslatorClassNames
+ */
+ public function testProcessRemovesDataCollectorTranslatorIfItDoesNotImplementTranslatorBagInterface($class)
+ {
+ $this->container->register('translator', $class);
+
+ $this->dataCollectorTranslatorPass->process($this->container);
+
+ $this->assertFalse($this->container->hasDefinition('translator.data_collector'));
+ }
+
+ /**
+ * @dataProvider getNotImplementingTranslatorBagInterfaceTranslatorClassNames
+ */
+ public function testProcessRemovesDataCollectorIfTranslatorDoesNotImplementTranslatorBagInterface($class)
+ {
+ $this->container->register('translator', $class);
+
+ $this->dataCollectorTranslatorPass->process($this->container);
+
+ $this->assertFalse($this->container->hasDefinition('data_collector.translation'));
+ }
+
+ public function getNotImplementingTranslatorBagInterfaceTranslatorClassNames()
+ {
+ return array(
+ array('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TranslatorWithTranslatorBag'),
+ array('%translator_not_implementing_bag%'),
+ );
+ }
+}
+
+class TranslatorWithTranslatorBag implements TranslatorInterface
+{
+ public function trans($id, array $parameters = array(), $domain = null, $locale = null)
+ {
+ }
+
+ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
+ {
+ }
+
+ public function setLocale($locale)
+ {
+ }
+
+ public function getLocale()
+ {
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
index ec80b9551063f..9adbaf8da9062 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
@@ -18,9 +19,11 @@
use Symfony\Component\Form\AbstractType;
/**
+ * @group legacy
+ *
* @author Bernhard Schussek
*/
-class FormPassTest extends \PHPUnit_Framework_TestCase
+class FormPassTest extends TestCase
{
public function testDoNothingIfFormExtensionNotLoaded()
{
@@ -178,7 +181,7 @@ public function testAddTaggedGuessers()
/**
* @dataProvider privateTaggedServicesProvider
*/
- public function testPrivateTaggedServices($id, $tagName, $expectedExceptionMessage)
+ public function testPrivateTaggedServices($id, $tagName)
{
$container = new ContainerBuilder();
$container->addCompilerPass(new FormPass());
@@ -192,19 +195,18 @@ public function testPrivateTaggedServices($id, $tagName, $expectedExceptionMessa
));
$container->setDefinition('form.extension', $extDefinition);
- $container->register($id, 'stdClass')->setPublic(false)->addTag($tagName);
-
- $this->setExpectedException('\InvalidArgumentException', $expectedExceptionMessage);
+ $container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, array('extended_type' => 'Foo'));
$container->compile();
+ $this->assertTrue($container->getDefinition($id)->isPublic());
}
public function privateTaggedServicesProvider()
{
return array(
- array('my.type', 'form.type', 'The service "my.type" must be public as form types are lazy-loaded'),
- array('my.type_extension', 'form.type_extension', 'The service "my.type_extension" must be public as form type extensions are lazy-loaded'),
- array('my.guesser', 'form.type_guesser', 'The service "my.guesser" must be public as form type guessers are lazy-loaded'),
+ array('my.type', 'form.type'),
+ array('my.type_extension', 'form.type_extension'),
+ array('my.guesser', 'form.type_guesser'),
);
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php
index 77f894faa9d68..eda507c621ebf 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php
@@ -11,15 +11,16 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
-class LoggingTranslatorPassTest extends \PHPUnit_Framework_TestCase
+class LoggingTranslatorPassTest extends TestCase
{
public function testProcess()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
- $parameterBag = $this->getMock('Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface');
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock();
+ $parameterBag = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface')->getMock();
$container->expects($this->exactly(2))
->method('hasAlias')
@@ -54,13 +55,18 @@ public function testProcess()
->method('getParameterBag')
->will($this->returnValue($parameterBag));
+ $container->expects($this->once())
+ ->method('getReflectionClass')
+ ->with('Symfony\Bundle\FrameworkBundle\Translation\Translator')
+ ->will($this->returnValue(new \ReflectionClass('Symfony\Bundle\FrameworkBundle\Translation\Translator')));
+
$pass = new LoggingTranslatorPass();
$pass->process($container);
}
public function testThatCompilerPassIsIgnoredIfThereIsNotLoggerDefinition()
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock();
$container->expects($this->once())
->method('hasAlias')
->will($this->returnValue(false));
@@ -71,7 +77,7 @@ public function testThatCompilerPassIsIgnoredIfThereIsNotLoggerDefinition()
public function testThatCompilerPassIsIgnoredIfThereIsNotTranslatorDefinition()
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock();
$container->expects($this->at(0))
->method('hasAlias')
->will($this->returnValue(true));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php
index f2af872e3c1f9..e064ce9f17f02 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
-class ProfilerPassTest extends \PHPUnit_Framework_TestCase
+class ProfilerPassTest extends TestCase
{
private $profilerDefinition;
@@ -40,7 +41,7 @@ public function testTemplateNoIdThrowsException()
$builder = $this->createContainerMock($services);
- $this->setExpectedException('InvalidArgumentException');
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException');
$profilerPass = new ProfilerPass();
$profilerPass->process($builder);
@@ -75,10 +76,7 @@ public function testValidCollector()
private function createContainerMock($services)
{
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter')
- );
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter'))->getMock();
$container->expects($this->any())
->method('hasDefinition')
->with($this->equalTo('profiler'))
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php
index fca0f3461ff8a..19b25bccb9729 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php
@@ -11,48 +11,53 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
-class PropertyInfoPassTest extends \PHPUnit_Framework_TestCase
+/**
+ * @group legacy
+ */
+class PropertyInfoPassTest extends TestCase
{
- public function testServicesAreOrderedAccordingToPriority()
+ /**
+ * @dataProvider provideTags
+ */
+ public function testServicesAreOrderedAccordingToPriority($index, $tag)
{
- $services = array(
- 'n3' => array('tag' => array()),
- 'n1' => array('tag' => array('priority' => 200)),
- 'n2' => array('tag' => array('priority' => 100)),
- );
+ $container = new ContainerBuilder();
+
+ $definition = $container->register('property_info')->setArguments(array(null, null, null, null));
+ $container->register('n2')->addTag($tag, array('priority' => 100));
+ $container->register('n1')->addTag($tag, array('priority' => 200));
+ $container->register('n3')->addTag($tag);
- $expected = array(
+ $propertyInfoPass = new PropertyInfoPass();
+ $propertyInfoPass->process($container);
+
+ $expected = new IteratorArgument(array(
new Reference('n1'),
new Reference('n2'),
new Reference('n3'),
- );
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('findTaggedServiceIds'));
-
- $container
- ->expects($this->any())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue($services));
-
- $propertyInfoPass = new PropertyInfoPass();
+ ));
+ $this->assertEquals($expected, $definition->getArgument($index));
+ }
- $method = new \ReflectionMethod(
- 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass',
- 'findAndSortTaggedServices'
+ public function provideTags()
+ {
+ return array(
+ array(0, 'property_info.list_extractor'),
+ array(1, 'property_info.type_extractor'),
+ array(2, 'property_info.description_extractor'),
+ array(3, 'property_info.access_extractor'),
);
- $method->setAccessible(true);
-
- $actual = $method->invoke($propertyInfoPass, 'tag', $container);
-
- $this->assertEquals($expected, $actual);
}
public function testReturningEmptyArrayWhenNoService()
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('findTaggedServiceIds'));
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock();
$container
->expects($this->any())
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php
index 27f1636e8ce9d..8ad759e834592 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php
@@ -11,19 +11,23 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
/**
* Tests for the SerializerPass class.
*
+ * @group legacy
+ *
* @author Javier Lopez
*/
-class SerializerPassTest extends \PHPUnit_Framework_TestCase
+class SerializerPassTest extends TestCase
{
public function testThrowExceptionWhenNoNormalizers()
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('hasDefinition', 'findTaggedServiceIds'));
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds'))->getMock();
$container->expects($this->once())
->method('hasDefinition')
@@ -35,7 +39,7 @@ public function testThrowExceptionWhenNoNormalizers()
->with('serializer.normalizer')
->will($this->returnValue(array()));
- $this->setExpectedException('RuntimeException');
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException');
$serializerPass = new SerializerPass();
$serializerPass->process($container);
@@ -43,11 +47,8 @@ public function testThrowExceptionWhenNoNormalizers()
public function testThrowExceptionWhenNoEncoders()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
- );
+ $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();
$container->expects($this->once())
->method('hasDefinition')
@@ -61,11 +62,11 @@ public function testThrowExceptionWhenNoEncoders()
array()
));
- $container->expects($this->once())
+ $container->expects($this->any())
->method('getDefinition')
->will($this->returnValue($definition));
- $this->setExpectedException('RuntimeException');
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException');
$serializerPass = new SerializerPass();
$serializerPass->process($container);
@@ -73,34 +74,22 @@ public function testThrowExceptionWhenNoEncoders()
public function testServicesAreOrderedAccordingToPriority()
{
- $services = array(
- 'n3' => array('tag' => array()),
- 'n1' => array('tag' => array('priority' => 200)),
- 'n2' => array('tag' => array('priority' => 100)),
- );
-
- $expected = array(
- new Reference('n1'),
- new Reference('n2'),
- new Reference('n3'),
- );
+ $container = new ContainerBuilder();
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('findTaggedServiceIds'));
-
- $container->expects($this->any())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue($services));
+ $definition = $container->register('serializer')->setArguments(array(null, null));
+ $container->register('n2')->addTag('serializer.normalizer', array('priority' => 100))->addTag('serializer.encoder', array('priority' => 100));
+ $container->register('n1')->addTag('serializer.normalizer', array('priority' => 200))->addTag('serializer.encoder', array('priority' => 200));
+ $container->register('n3')->addTag('serializer.normalizer')->addTag('serializer.encoder');
$serializerPass = new SerializerPass();
+ $serializerPass->process($container);
- $method = new \ReflectionMethod(
- 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass',
- 'findAndSortTaggedServices'
+ $expected = array(
+ new Reference('n1'),
+ new Reference('n2'),
+ new Reference('n3'),
);
- $method->setAccessible(true);
-
- $actual = $method->invoke($serializerPass, 'tag', $container);
-
- $this->assertEquals($expected, $actual);
+ $this->assertEquals($expected, $definition->getArgument(0));
+ $this->assertEquals($expected, $definition->getArgument(1));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php
index 83f70514d5456..a92f734eccc0f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php
@@ -11,38 +11,40 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Reference;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
-class TranslatorPassTest extends \PHPUnit_Framework_TestCase
+class TranslatorPassTest extends TestCase
{
public function testValidCollector()
{
- $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
- $definition->expects($this->at(0))
- ->method('addMethodCall')
- ->with('addLoader', array('xliff', new Reference('xliff')));
- $definition->expects($this->at(1))
- ->method('addMethodCall')
- ->with('addLoader', array('xlf', new Reference('xliff')));
-
- $container = $this->getMock(
- 'Symfony\Component\DependencyInjection\ContainerBuilder',
- array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition')
- );
- $container->expects($this->any())
- ->method('hasDefinition')
- ->will($this->returnValue(true));
- $container->expects($this->once())
- ->method('getDefinition')
- ->will($this->returnValue($definition));
- $container->expects($this->once())
- ->method('findTaggedServiceIds')
- ->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf')))));
- $container->expects($this->once())
- ->method('findDefinition')
- ->will($this->returnValue($this->getMock('Symfony\Component\DependencyInjection\Definition')));
+ $loader = (new Definition())
+ ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'));
+
+ $translator = (new Definition())
+ ->setArguments(array(null, null, null, null));
+
+ $container = new ContainerBuilder();
+ $container->setDefinition('translator.default', $translator);
+ $container->setDefinition('translation.loader', $loader);
+
$pass = new TranslatorPass();
$pass->process($container);
+
+ $expected = (new Definition())
+ ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'))
+ ->addMethodCall('addLoader', array('xliff', new Reference('translation.loader')))
+ ->addMethodCall('addLoader', array('xlf', new Reference('translation.loader')))
+ ;
+ $this->assertEquals($expected, $loader);
+
+ $this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3));
+
+ $expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader')));
+ $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php
index f354007bb982d..6c6f15899559c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php
@@ -11,28 +11,19 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
-class UnusedTagsPassTest extends \PHPUnit_Framework_TestCase
+class UnusedTagsPassTest extends TestCase
{
public function testProcess()
{
$pass = new UnusedTagsPass();
- $formatter = $this->getMock('Symfony\Component\DependencyInjection\Compiler\LoggingFormatter');
- $formatter
- ->expects($this->at(0))
- ->method('format')
- ->with($pass, 'Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?')
- ;
-
- $compiler = $this->getMock('Symfony\Component\DependencyInjection\Compiler\Compiler');
- $compiler->expects($this->once())->method('getLoggingFormatter')->will($this->returnValue($formatter));
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder',
- array('findTaggedServiceIds', 'getCompiler', 'findUnusedTags', 'findTags')
- );
- $container->expects($this->once())->method('getCompiler')->will($this->returnValue($compiler));
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'findUnusedTags', 'findTags', 'log'))->getMock();
+ $container->expects($this->once())
+ ->method('log')
+ ->with($pass, 'Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?');
$container->expects($this->once())
->method('findTags')
->will($this->returnValue(array('kenrel.event_subscriber')));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
index adfc46d14fb52..353e959c68ebf 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -11,10 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration;
+use Symfony\Bundle\FullStack;
+use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Processor;
-class ConfigurationTest extends \PHPUnit_Framework_TestCase
+class ConfigurationTest extends TestCase
{
public function testDefaultConfig()
{
@@ -40,67 +43,6 @@ public function testDoNoDuplicateDefaultFormResources()
$this->assertEquals(array('FrameworkBundle:Form'), $config['templating']['form']['resources']);
}
- /**
- * @dataProvider getTestValidTrustedProxiesData
- */
- public function testValidTrustedProxies($trustedProxies, $processedProxies)
- {
- $processor = new Processor();
- $configuration = new Configuration(true);
- $config = $processor->processConfiguration($configuration, array(array(
- 'secret' => 's3cr3t',
- 'trusted_proxies' => $trustedProxies,
- )));
-
- $this->assertEquals($processedProxies, $config['trusted_proxies']);
- }
-
- public function getTestValidTrustedProxiesData()
- {
- return array(
- array(array('127.0.0.1'), array('127.0.0.1')),
- array(array('::1'), array('::1')),
- array(array('127.0.0.1', '::1'), array('127.0.0.1', '::1')),
- array(null, array()),
- array(false, array()),
- array(array(), array()),
- array(array('10.0.0.0/8'), array('10.0.0.0/8')),
- array(array('::ffff:0:0/96'), array('::ffff:0:0/96')),
- array(array('0.0.0.0/0'), array('0.0.0.0/0')),
- );
- }
-
- /**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- */
- public function testInvalidTypeTrustedProxies()
- {
- $processor = new Processor();
- $configuration = new Configuration(true);
- $processor->processConfiguration($configuration, array(
- array(
- 'secret' => 's3cr3t',
- 'trusted_proxies' => 'Not an IP address',
- ),
- ));
- }
-
- /**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- */
- public function testInvalidValueTrustedProxies()
- {
- $processor = new Processor();
- $configuration = new Configuration(true);
-
- $processor->processConfiguration($configuration, array(
- array(
- 'secret' => 's3cr3t',
- 'trusted_proxies' => array('Not an IP address'),
- ),
- ));
- }
-
public function testAssetsCanBeEnabled()
{
$processor = new Processor();
@@ -115,68 +57,80 @@ public function testAssetsCanBeEnabled()
'base_path' => '',
'base_urls' => array(),
'packages' => array(),
+ 'json_manifest_path' => null,
);
$this->assertEquals($defaultConfig, $config['assets']);
}
/**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- * @expectedExceptionMessage You cannot use both "version_strategy" and "version" at the same time under "assets".
+ * @dataProvider provideInvalidAssetConfigurationTests
*/
- public function testInvalidVersionStrategy()
+ public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMessage)
{
+ $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
+ InvalidConfigurationException::class,
+ $expectedMessage
+ );
+ if (method_exists($this, 'expectExceptionMessage')) {
+ $this->expectExceptionMessage($expectedMessage);
+ }
+
$processor = new Processor();
$configuration = new Configuration(true);
$processor->processConfiguration($configuration, array(
- array(
- 'assets' => array(
- 'base_urls' => '//example.com',
- 'version' => 1,
- 'version_strategy' => 'foo',
+ array(
+ 'assets' => $assetConfig,
),
- ),
- ));
+ ));
}
- /**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- * @expectedExceptionMessage You cannot use both "version_strategy" and "version" at the same time under "assets" packages.
- */
- public function testInvalidPackageVersionStrategy()
+ public function provideInvalidAssetConfigurationTests()
{
- $processor = new Processor();
- $configuration = new Configuration(true);
-
- $processor->processConfiguration($configuration, array(
- array(
- 'assets' => array(
- 'base_urls' => '//example.com',
- 'version' => 1,
- 'packages' => array(
- 'foo' => array(
- 'base_urls' => '//example.com',
- 'version' => 1,
- 'version_strategy' => 'foo',
- ),
- ),
+ // helper to turn config into embedded package config
+ $createPackageConfig = function (array $packageConfig) {
+ return array(
+ 'base_urls' => '//example.com',
+ 'version' => 1,
+ 'packages' => array(
+ 'foo' => $packageConfig,
),
- ),
- ));
+ );
+ };
+
+ $config = array(
+ 'version' => 1,
+ 'version_strategy' => 'foo',
+ );
+ yield array($config, 'You cannot use both "version_strategy" and "version" at the same time under "assets".');
+ yield array($createPackageConfig($config), 'You cannot use both "version_strategy" and "version" at the same time under "assets" packages.');
+
+ $config = array(
+ 'json_manifest_path' => '/foo.json',
+ 'version_strategy' => 'foo',
+ );
+ yield array($config, 'You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".');
+ yield array($createPackageConfig($config), 'You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.');
+
+ $config = array(
+ 'json_manifest_path' => '/foo.json',
+ 'version' => '1',
+ );
+ yield array($config, 'You cannot use both "version" and "json_manifest_path" at the same time under "assets".');
+ yield array($createPackageConfig($config), 'You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.');
}
protected static function getBundleDefaultConfig()
{
return array(
'http_method_override' => true,
- 'trusted_proxies' => array(),
'ide' => null,
'default_locale' => 'en',
'csrf_protection' => array(
'enabled' => false,
),
'form' => array(
- 'enabled' => false,
+ 'enabled' => !class_exists(FullStack::class),
'csrf_protection' => array(
'enabled' => null, // defaults to csrf_protection.enabled
'field_name' => '_token',
@@ -200,17 +154,20 @@ protected static function getBundleDefaultConfig()
),
),
'translator' => array(
- 'enabled' => false,
+ 'enabled' => !class_exists(FullStack::class),
'fallbacks' => array('en'),
'logging' => true,
'paths' => array(),
),
'validation' => array(
- 'enabled' => false,
- 'enable_annotations' => false,
+ 'enabled' => !class_exists(FullStack::class),
+ 'enable_annotations' => !class_exists(FullStack::class),
'static_method' => array('loadValidatorMetadata'),
'translation_domain' => 'validators',
'strict_email' => false,
+ 'mapping' => array(
+ 'paths' => array(),
+ ),
),
'annotations' => array(
'cache' => 'php_array',
@@ -219,8 +176,9 @@ protected static function getBundleDefaultConfig()
'enabled' => true,
),
'serializer' => array(
- 'enabled' => false,
- 'enable_annotations' => false,
+ 'enabled' => !class_exists(FullStack::class),
+ 'enable_annotations' => !class_exists(FullStack::class),
+ 'mapping' => array('paths' => array()),
),
'property_access' => array(
'magic_call' => false,
@@ -258,13 +216,14 @@ protected static function getBundleDefaultConfig()
'loaders' => array(),
),
'assets' => array(
- 'enabled' => false,
+ 'enabled' => !class_exists(FullStack::class),
'version_strategy' => null,
'version' => null,
'version_format' => '%%s?%%s',
'base_path' => '',
'base_urls' => array(),
'packages' => array(),
+ 'json_manifest_path' => null,
),
'cache' => array(
'pools' => array(),
@@ -272,12 +231,16 @@ protected static function getBundleDefaultConfig()
'system' => 'cache.adapter.system',
'directory' => '%kernel.cache_dir%/pools',
'default_redis_provider' => 'redis://localhost',
+ 'default_memcached_provider' => 'memcached://localhost',
),
'workflows' => array(),
'php_errors' => array(
'log' => true,
'throw' => true,
),
+ 'web_link' => array(
+ 'enabled' => !class_exists(FullStack::class),
+ ),
);
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/Resources/config/validation.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/Resources/config/validation.xml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/Resources/config/validation.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/Resources/config/validation.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php
new file mode 100644
index 0000000000000..166b606a459e2
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php
@@ -0,0 +1,22 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class CustomPathBundle extends Bundle
+{
+ public function getPath()
+ {
+ return __DIR__.'/..';
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.xml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.xml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/files/foo.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/files/foo.xml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/files/foo.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/files/foo.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php
index b0c4548fa07de..2f090b2de8d53 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php
@@ -11,6 +11,8 @@
namespace Symfony\Bundle\FrameworkBundle\Tests;
-class TestBundle extends \Symfony\Component\HttpKernel\Bundle\Bundle
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class TestBundle extends Bundle
{
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
index 3cfc5c1bc0cc4..dc6bf7bb8df55 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
@@ -24,6 +24,9 @@
'base_urls' => array('https://bar2.example.com'),
'version_strategy' => 'assets.custom_version_strategy',
),
+ 'json_manifest_strategy' => array(
+ 'json_manifest_path' => '/path/to/manifest.json',
+ ),
),
),
));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_env_var.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_env_var.php
new file mode 100644
index 0000000000000..b93ade8f4c816
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_env_var.php
@@ -0,0 +1,9 @@
+setParameter('env(REDIS_URL)', 'redis://paas.com');
+
+$container->loadFromExtension('framework', array(
+ 'cache' => array(
+ 'default_redis_provider' => '%env(REDIS_URL)%',
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
index 9173dd5615bda..58a4340e6979f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -10,7 +10,6 @@
),
),
'http_method_override' => false,
- 'trusted_proxies' => array('127.0.0.1', '10.0.0.1'),
'esi' => array(
'enabled' => true,
),
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php
new file mode 100644
index 0000000000000..4e437bf4e8e1c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php
@@ -0,0 +1,15 @@
+loadFromExtension('framework', array(
+ 'annotations' => array('enabled' => true),
+ 'serializer' => array(
+ 'enable_annotations' => true,
+ 'mapping' => array(
+ 'paths' => array(
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files',
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml',
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml',
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_disabled.php
new file mode 100644
index 0000000000000..4fb2aec557f67
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_disabled.php
@@ -0,0 +1,8 @@
+loadFromExtension('framework', array(
+ 'translator' => false,
+ 'templating' => array(
+ 'engines' => array('php'),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_enabled.php
new file mode 100644
index 0000000000000..b8053c853b128
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_translator_enabled.php
@@ -0,0 +1,8 @@
+loadFromExtension('framework', array(
+ 'translator' => true,
+ 'templating' => array(
+ 'engines' => array('php'),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php
new file mode 100644
index 0000000000000..51bbb90ef48a6
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php
@@ -0,0 +1,13 @@
+loadFromExtension('framework', array(
+ 'validation' => array(
+ 'mapping' => array(
+ 'paths' => array(
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files',
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml',
+ '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml',
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php
new file mode 100644
index 0000000000000..990064cca934e
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php
@@ -0,0 +1,5 @@
+loadFromExtension('framework', array(
+ 'web_link' => array('enabled' => true),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php
new file mode 100644
index 0000000000000..2619a2dd4316a
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php
@@ -0,0 +1,49 @@
+loadFromExtension('framework', array(
+ 'workflows' => array(
+ 'article' => array(
+ 'type' => 'workflow',
+ 'marking_store' => array(
+ 'type' => 'multiple_state',
+ ),
+ 'supports' => array(
+ FrameworkExtensionTest::class,
+ ),
+ 'initial_place' => 'draft',
+ 'places' => array(
+ 'draft',
+ 'wait_for_journalist',
+ 'approved_by_journalist',
+ 'wait_for_spellchecker',
+ 'approved_by_spellchecker',
+ 'published',
+ ),
+ 'transitions' => array(
+ 'request_review' => array(
+ 'from' => 'draft',
+ 'to' => array('wait_for_journalist', 'wait_for_spellchecker'),
+ ),
+ 'journalist_approval' => array(
+ 'from' => 'wait_for_journalist',
+ 'to' => 'approved_by_journalist',
+ ),
+ 'spellchecker_approval' => array(
+ 'from' => 'wait_for_spellchecker',
+ 'to' => 'approved_by_spellchecker',
+ ),
+ 'publish' => array(
+ 'from' => array('approved_by_journalist', 'approved_by_spellchecker'),
+ 'to' => 'published',
+ ),
+ 'publish_editor_in_chief' => array(
+ 'name' => 'publish',
+ 'from' => 'draft',
+ 'to' => 'published',
+ ),
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php
new file mode 100644
index 0000000000000..062fdb9f0dba4
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php
@@ -0,0 +1,31 @@
+loadFromExtension('framework', array(
+ 'workflows' => array(
+ 'my_workflow' => array(
+ 'marking_store' => array(
+ 'type' => 'multiple_state',
+ ),
+ 'supports' => array(
+ FrameworkExtensionTest::class,
+ ),
+ 'support_strategy' => 'foobar',
+ 'places' => array(
+ 'first',
+ 'last',
+ ),
+ 'transitions' => array(
+ 'go' => array(
+ 'from' => array(
+ 'first',
+ ),
+ 'to' => array(
+ 'last',
+ ),
+ ),
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php
new file mode 100644
index 0000000000000..06948785e927c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php
@@ -0,0 +1,27 @@
+loadFromExtension('framework', array(
+ 'workflows' => array(
+ 'my_workflow' => array(
+ 'marking_store' => array(
+ 'type' => 'multiple_state',
+ ),
+ 'places' => array(
+ 'first',
+ 'last',
+ ),
+ 'transitions' => array(
+ 'go' => array(
+ 'from' => array(
+ 'first',
+ ),
+ 'to' => array(
+ 'last',
+ ),
+ ),
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php
index 854a858415e00..c527606561ee9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php
@@ -88,5 +88,24 @@
),
),
),
+ 'service_marking_store_workflow' => array(
+ 'type' => 'workflow',
+ 'marking_store' => array(
+ 'service' => 'workflow_service',
+ ),
+ 'supports' => array(
+ FrameworkExtensionTest::class,
+ ),
+ 'places' => array(
+ 'first',
+ 'last',
+ ),
+ 'transitions' => array(
+ 'go' => array(
+ 'from' => 'first',
+ 'to' => 'last',
+ ),
+ ),
+ ),
),
));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php
new file mode 100644
index 0000000000000..63e83170fca52
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php
@@ -0,0 +1,26 @@
+loadFromExtension('framework', array(
+ 'workflows' => array(
+ 'missing_type' => array(
+ 'marking_store' => array(
+ 'service' => 'workflow_service',
+ ),
+ 'supports' => array(
+ \stdClass::class,
+ ),
+ 'places' => array(
+ 'first',
+ 'last',
+ ),
+ 'transitions' => array(
+ 'go' => array(
+ 'from' => 'first',
+ 'to' => 'last',
+ ),
+ ),
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
index b99952b2923d3..a907a5b967f93 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
@@ -21,6 +21,7 @@
https://bar_version_strategy.example.com
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_env_var.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_env_var.xml
new file mode 100644
index 0000000000000..8f03cb1784b35
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_env_var.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ redis://paas.com
+
+
+
+
+ %env(REDIS_URL)%
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
index 7c6b11ac44aa6..5c6a221c18489 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -6,7 +6,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml
new file mode 100644
index 0000000000000..9fec09f0dbf0f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_disabled.xml
new file mode 100644
index 0000000000000..72a78aaf0c090
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_disabled.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ php
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_enabled.xml
new file mode 100644
index 0000000000000..036afa38f7034
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_php_translator_enabled.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ php
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml
new file mode 100644
index 0000000000000..c011269bd370d
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml
+ %kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml
new file mode 100644
index 0000000000000..a061f0b15b9ed
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml
new file mode 100644
index 0000000000000..d52aed8c95234
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+ a
+ a
+
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ draft
+ wait_for_journalist
+ approved_by_journalist
+ wait_for_spellchecker
+ approved_by_spellchecker
+ published
+
+ draft
+ wait_for_journalist
+ wait_for_spellchecker
+
+
+ wait_for_journalist
+ approved_by_journalist
+
+
+ wait_for_spellchecker
+ approved_by_spellchecker
+
+
+ approved_by_journalist
+ approved_by_spellchecker
+ published
+
+
+ draft
+ published
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml
new file mode 100644
index 0000000000000..92e26ff327d94
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ first
+ last
+
+ a
+ a
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml
new file mode 100644
index 0000000000000..14bb287cca489
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+ first
+ last
+
+ a
+ a
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml
index 924ff75111ca8..be065c4558858 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml
@@ -79,5 +79,16 @@
review
+
+
+
+ Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ first
+ last
+
+ first
+ last
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml
new file mode 100644
index 0000000000000..2e6ebad552b74
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ stdClass
+ first
+ last
+
+ first
+ last
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
index 73cd9234e7060..a1679e389ddbf 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
@@ -17,3 +17,5 @@ framework:
bar_version_strategy:
base_urls: ["https://bar_version_strategy.example.com"]
version_strategy: assets.custom_version_strategy
+ json_manifest_strategy:
+ json_manifest_path: '/path/to/manifest.json'
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_env_var.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_env_var.yml
new file mode 100644
index 0000000000000..1d9ce5f7f02f7
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_env_var.yml
@@ -0,0 +1,6 @@
+parameters:
+ env(REDIS_URL): redis://paas.com
+
+framework:
+ cache:
+ default_redis_provider: "%env(REDIS_URL)%"
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
index 237654880c984..f471372097c15 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -6,7 +6,6 @@ framework:
csrf_protection:
field_name: _csrf
http_method_override: false
- trusted_proxies: ['127.0.0.1', '10.0.0.1']
esi:
enabled: true
profiler:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml
new file mode 100644
index 0000000000000..b977dc89be52f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml
@@ -0,0 +1,10 @@
+framework:
+ annotations:
+ enabled: true
+ serializer:
+ enable_annotations: true
+ mapping:
+ paths:
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files"
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml"
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml"
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_disabled.yml
new file mode 100644
index 0000000000000..fe0f3e83b5683
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_disabled.yml
@@ -0,0 +1,4 @@
+framework:
+ translator: false
+ templating:
+ engines: [php]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_enabled.yml
new file mode 100644
index 0000000000000..0991a2007d77f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_translator_enabled.yml
@@ -0,0 +1,4 @@
+framework:
+ translator: true
+ templating:
+ engines: [php]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml
new file mode 100644
index 0000000000000..7d79bc9a1c477
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml
@@ -0,0 +1,7 @@
+framework:
+ validation:
+ mapping:
+ paths:
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files"
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml"
+ - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml"
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml
new file mode 100644
index 0000000000000..4276aacbe21c1
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml
@@ -0,0 +1,3 @@
+framework:
+ web_link:
+ enabled: true
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml
new file mode 100644
index 0000000000000..36d00de46501c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml
@@ -0,0 +1,33 @@
+framework:
+ workflows:
+ article:
+ type: workflow
+ marking_store:
+ type: multiple_state
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ initial_place: draft
+ places:
+ - draft
+ - wait_for_journalist
+ - approved_by_journalist
+ - wait_for_spellchecker
+ - approved_by_spellchecker
+ - published
+ transitions:
+ request_review:
+ from: [draft]
+ to: [wait_for_journalist, wait_for_spellchecker]
+ journalist_approval:
+ from: [wait_for_journalist]
+ to: [approved_by_journalist]
+ spellchecker_approval:
+ from: [wait_for_spellchecker]
+ to: [approved_by_spellchecker]
+ publish:
+ from: [approved_by_journalist, approved_by_spellchecker]
+ to: [published]
+ publish_editor_in_chief:
+ name: publish
+ from: [draft]
+ to: [published]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml
new file mode 100644
index 0000000000000..743708485ce65
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml
@@ -0,0 +1,17 @@
+framework:
+ workflows:
+ my_workflow:
+ marking_store:
+ type: multiple_state
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ support_strategy: foobar
+ places:
+ - first
+ - last
+ transitions:
+ go:
+ from:
+ - first
+ to:
+ - last
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml
new file mode 100644
index 0000000000000..6dc848d936b21
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml
@@ -0,0 +1,14 @@
+framework:
+ workflows:
+ my_workflow:
+ marking_store:
+ type: multiple_state
+ places:
+ - first
+ - last
+ transitions:
+ go:
+ from:
+ - first
+ to:
+ - last
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml
index a933db5100fc8..36b84f71e4582 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml
@@ -63,3 +63,18 @@ framework:
reopen:
from: closed
to: review
+ service_marking_store_workflow:
+ type: workflow
+ marking_store:
+ service: workflow_service
+ supports:
+ - Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
+ places:
+ - first
+ - last
+ transitions:
+ go:
+ from:
+ - first
+ to:
+ - last
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml
new file mode 100644
index 0000000000000..41b81683ba445
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml
@@ -0,0 +1,7 @@
+framework:
+ workflows:
+ missing_type:
+ supports: stdClass
+ places: [ first, second ]
+ transitions:
+ go: {from: first, to: last }
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index c1ee84685654f..4f86c85d4f8fb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -11,26 +11,37 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection;
+use Doctrine\Common\Annotations\Annotation;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
+use Symfony\Bundle\FullStack;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
+use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\ProxyAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\PropertyAccess\PropertyAccessor;
+use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
+use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
+use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
abstract class FrameworkExtensionTest extends TestCase
{
@@ -67,6 +78,32 @@ public function testPropertyAccessWithOverriddenValues()
$this->assertTrue($def->getArgument(1));
}
+ public function testPropertyAccessCache()
+ {
+ $container = $this->createContainerFromFile('property_accessor');
+
+ if (!method_exists(PropertyAccessor::class, 'createCache')) {
+ return $this->assertFalse($container->hasDefinition('cache.property_access'));
+ }
+
+ $cache = $container->getDefinition('cache.property_access');
+ $this->assertSame(array(PropertyAccessor::class, 'createCache'), $cache->getFactory(), 'PropertyAccessor::createCache() should be used in non-debug mode');
+ $this->assertSame(AdapterInterface::class, $cache->getClass());
+ }
+
+ public function testPropertyAccessCacheWithDebug()
+ {
+ $container = $this->createContainerFromFile('property_accessor', array('kernel.debug' => true));
+
+ if (!method_exists(PropertyAccessor::class, 'createCache')) {
+ return $this->assertFalse($container->hasDefinition('cache.property_access'));
+ }
+
+ $cache = $container->getDefinition('cache.property_access');
+ $this->assertNull($cache->getFactory());
+ $this->assertSame(ArrayAdapter::class, $cache->getClass(), 'ArrayAdapter should be used in debug mode');
+ }
+
/**
* @expectedException \LogicException
* @expectedExceptionMessage CSRF protection needs sessions to be enabled.
@@ -83,13 +120,6 @@ public function testCsrfProtectionForFormsEnablesCsrfProtectionAutomatically()
$this->assertTrue($container->hasDefinition('security.csrf.token_manager'));
}
- public function testProxies()
- {
- $container = $this->createContainerFromFile('full');
-
- $this->assertEquals(array('127.0.0.1', '10.0.0.1'), $container->getParameter('kernel.trusted_proxies'));
- }
-
public function testHttpMethodOverride()
{
$container = $this->createContainerFromFile('full');
@@ -165,6 +195,25 @@ public function testWorkflows()
$this->assertSame(array('workflow.definition' => array(array('name' => 'pull_request', 'type' => 'state_machine', 'marking_store' => 'single_state'))), $stateMachineDefinition->getTags());
$this->assertCount(9, $stateMachineDefinition->getArgument(1));
$this->assertSame('start', $stateMachineDefinition->getArgument(2));
+
+ $serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
+ /** @var Reference $markingStoreRef */
+ $markingStoreRef = $serviceMarkingStoreWorkflowDefinition->getArgument(1);
+ $this->assertInstanceOf(Reference::class, $markingStoreRef);
+ $this->assertEquals('workflow_service', (string) $markingStoreRef);
+
+ $this->assertTrue($container->hasDefinition('workflow.registry', 'Workflow registry is registered as a service'));
+ $registryDefinition = $container->getDefinition('workflow.registry');
+ $this->assertGreaterThan(0, count($registryDefinition->getMethodCalls()));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation The "type" option of the "framework.workflows.missing_type" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.
+ */
+ public function testDeprecatedWorkflowMissingType()
+ {
+ $container = $this->createContainerFromFile('workflows_without_type');
}
/**
@@ -176,6 +225,24 @@ public function testWorkflowCannotHaveBothTypeAndService()
$this->createContainerFromFile('workflow_with_type_and_service');
}
+ /**
+ * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
+ * @expectedExceptionMessage "supports" and "support_strategy" cannot be used together.
+ */
+ public function testWorkflowCannotHaveBothSupportsAndSupportStrategy()
+ {
+ $this->createContainerFromFile('workflow_with_support_and_support_strategy');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
+ * @expectedExceptionMessage "supports" or "support_strategy" should be configured.
+ */
+ public function testWorkflowShouldHaveOneOfSupportsAndSupportStrategy()
+ {
+ $this->createContainerFromFile('workflow_without_support_and_support_strategy');
+ }
+
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage "arguments" and "service" cannot be used together.
@@ -185,6 +252,29 @@ public function testWorkflowCannotHaveBothArgumentsAndService()
$this->createContainerFromFile('workflow_with_arguments_and_service');
}
+ public function testWorkflowMultipleTransitionsWithSameName()
+ {
+ $container = $this->createContainerFromFile('workflow_with_multiple_transitions_with_same_name');
+
+ $this->assertTrue($container->hasDefinition('workflow.article', 'Workflow is registered as a service'));
+ $this->assertTrue($container->hasDefinition('workflow.article.definition', 'Workflow definition is registered as a service'));
+
+ $workflowDefinition = $container->getDefinition('workflow.article.definition');
+
+ $transitions = $workflowDefinition->getArgument(1);
+
+ $this->assertCount(5, $transitions);
+
+ $this->assertSame('request_review', $transitions[0]->getArgument(0));
+ $this->assertSame('journalist_approval', $transitions[1]->getArgument(0));
+ $this->assertSame('spellchecker_approval', $transitions[2]->getArgument(0));
+ $this->assertSame('publish', $transitions[3]->getArgument(0));
+ $this->assertSame('publish', $transitions[4]->getArgument(0));
+
+ $this->assertSame(array('approved_by_journalist', 'approved_by_spellchecker'), $transitions[3]->getArgument(1));
+ $this->assertSame(array('draft'), $transitions[4]->getArgument(1));
+ }
+
public function testRouter()
{
$container = $this->createContainerFromFile('full');
@@ -289,27 +379,32 @@ public function testAssets()
$packages = $container->getDefinition('assets.packages');
// default package
- $defaultPackage = $container->getDefinition($packages->getArgument(0));
+ $defaultPackage = $container->getDefinition((string) $packages->getArgument(0));
$this->assertUrlPackage($container, $defaultPackage, array('http://cdn.example.com'), 'SomeVersionScheme', '%%s?version=%%s');
// packages
$packages = $packages->getArgument(1);
- $this->assertCount(5, $packages);
+ $this->assertCount(6, $packages);
- $package = $container->getDefinition($packages['images_path']);
+ $package = $container->getDefinition((string) $packages['images_path']);
$this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s');
- $package = $container->getDefinition($packages['images']);
+ $package = $container->getDefinition((string) $packages['images']);
$this->assertUrlPackage($container, $package, array('http://images1.example.com', 'http://images2.example.com'), '1.0.0', '%%s?version=%%s');
- $package = $container->getDefinition($packages['foo']);
+ $package = $container->getDefinition((string) $packages['foo']);
$this->assertPathPackage($container, $package, '', '1.0.0', '%%s-%%s');
- $package = $container->getDefinition($packages['bar']);
+ $package = $container->getDefinition((string) $packages['bar']);
$this->assertUrlPackage($container, $package, array('https://bar2.example.com'), 'SomeVersionScheme', '%%s?version=%%s');
- $package = $container->getDefinition($packages['bar_version_strategy']);
+ $package = $container->getDefinition((string) $packages['bar_version_strategy']);
$this->assertEquals('assets.custom_version_strategy', (string) $package->getArgument(1));
+
+ $package = $container->getDefinition((string) $packages['json_manifest_strategy']);
+ $versionStrategy = $container->getDefinition((string) $package->getArgument(1));
+ $this->assertEquals('assets.json_manifest_version_strategy', $versionStrategy->getParent());
+ $this->assertEquals('/path/to/manifest.json', $versionStrategy->getArgument(0));
}
public function testAssetsDefaultVersionStrategyAsService()
@@ -318,18 +413,24 @@ public function testAssetsDefaultVersionStrategyAsService()
$packages = $container->getDefinition('assets.packages');
// default package
- $defaultPackage = $container->getDefinition($packages->getArgument(0));
+ $defaultPackage = $container->getDefinition((string) $packages->getArgument(0));
$this->assertEquals('assets.custom_version_strategy', (string) $defaultPackage->getArgument(1));
}
+ public function testWebLink()
+ {
+ $container = $this->createContainerFromFile('web_link');
+ $this->assertTrue($container->hasDefinition('web_link.add_link_header_listener'));
+ }
+
public function testTranslator()
{
$container = $this->createContainerFromFile('full');
$this->assertTrue($container->hasDefinition('translator.default'), '->registerTranslatorConfiguration() loads translation.xml');
$this->assertEquals('translator.default', (string) $container->getAlias('translator'), '->registerTranslatorConfiguration() redefines translator service from identity to real translator');
- $options = $container->getDefinition('translator.default')->getArgument(3);
+ $options = $container->getDefinition('translator.default')->getArgument(4);
- $files = array_map(function ($resource) { return realpath($resource); }, $options['resource_files']['en']);
+ $files = array_map('realpath', $options['resource_files']['en']);
$ref = new \ReflectionClass('Symfony\Component\Validator\Validation');
$this->assertContains(
strtr(dirname($ref->getFileName()).'/Resources/translations/validators.en.xlf', '/', DIRECTORY_SEPARATOR),
@@ -366,6 +467,20 @@ public function testTranslatorMultipleFallbacks()
$this->assertEquals(array('en', 'fr'), $calls[1][1][0]);
}
+ public function testTranslatorHelperIsRegisteredWhenTranslatorIsEnabled()
+ {
+ $container = $this->createContainerFromFile('templating_php_translator_enabled');
+
+ $this->assertTrue($container->has('templating.helper.translator'));
+ }
+
+ public function testTranslatorHelperIsNotRegisteredWhenTranslatorIsDisabled()
+ {
+ $container = $this->createContainerFromFile('templating_php_translator_disabled');
+
+ $this->assertFalse($container->has('templating.helper.translator'));
+ }
+
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
@@ -385,7 +500,9 @@ public function testValidation()
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
- $this->assertCount(6, $calls);
+ $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class);
+
+ $this->assertCount($annotations ? 7 : 6, $calls);
$this->assertSame('setConstraintValidatorFactory', $calls[0][0]);
$this->assertEquals(array(new Reference('validator.validator_factory')), $calls[0][1]);
$this->assertSame('setTranslator', $calls[1][0]);
@@ -394,10 +511,14 @@ public function testValidation()
$this->assertSame(array('%validator.translation_domain%'), $calls[2][1]);
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertSame(array($xmlMappings), $calls[3][1]);
- $this->assertSame('addMethodMapping', $calls[4][0]);
- $this->assertSame(array('loadValidatorMetadata'), $calls[4][1]);
- $this->assertSame('setMetadataCache', $calls[5][0]);
- $this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[5][1]);
+ $i = 3;
+ if ($annotations) {
+ $this->assertSame('enableAnnotationMapping', $calls[++$i][0]);
+ }
+ $this->assertSame('addMethodMapping', $calls[++$i][0]);
+ $this->assertSame(array('loadValidatorMetadata'), $calls[$i][1]);
+ $this->assertSame('setMetadataCache', $calls[++$i][0]);
+ $this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[$i][1]);
}
public function testValidationService()
@@ -412,12 +533,15 @@ public function testAnnotations()
$container = $this->createContainerFromFile('full');
$this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.filesystem_cache')->getArgument(0));
- $this->assertSame('annotations.cached_reader', (string) $container->getAlias('annotation_reader'));
$this->assertSame('annotations.filesystem_cache', (string) $container->getDefinition('annotations.cached_reader')->getArgument(1));
}
public function testFileLinkFormat()
{
+ if (ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {
+ $this->markTestSkipped('A custom file_link_format is defined.');
+ }
+
$container = $this->createContainerFromFile('full');
$this->assertEquals('file%link%format', $container->getParameter('debug.file_link_format'));
@@ -444,7 +568,8 @@ public function testValidationPaths()
require_once __DIR__.'/Fixtures/TestBundle/TestBundle.php';
$container = $this->createContainerFromFile('validation_annotations', array(
- 'kernel.bundles' => array('TestBundle' => 'Symfony\Bundle\FrameworkBundle\Tests\TestBundle'),
+ 'kernel.bundles' => array('TestBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\TestBundle'),
+ 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/TestBundle')),
));
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
@@ -474,19 +599,68 @@ public function testValidationPaths()
$this->assertStringEndsWith('TestBundle/Resources/config/validation.yml', $yamlMappings[0]);
}
+ public function testValidationPathsUsingCustomBundlePath()
+ {
+ require_once __DIR__.'/Fixtures/CustomPathBundle/src/CustomPathBundle.php';
+
+ $container = $this->createContainerFromFile('validation_annotations', array(
+ 'kernel.bundles' => array('CustomPathBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\CustomPathBundle'),
+ 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/CustomPathBundle')),
+ ));
+
+ $calls = $container->getDefinition('validator.builder')->getMethodCalls();
+ $xmlMappings = $calls[3][1][0];
+ $this->assertCount(2, $xmlMappings);
+
+ try {
+ // Testing symfony/symfony
+ $this->assertStringEndsWith('Component'.DIRECTORY_SEPARATOR.'Form/Resources/config/validation.xml', $xmlMappings[0]);
+ } catch (\Exception $e) {
+ // Testing symfony/framework-bundle with deps=high
+ $this->assertStringEndsWith('symfony'.DIRECTORY_SEPARATOR.'form/Resources/config/validation.xml', $xmlMappings[0]);
+ }
+ $this->assertStringEndsWith('CustomPathBundle/Resources/config/validation.xml', $xmlMappings[1]);
+
+ $yamlMappings = $calls[4][1][0];
+ $this->assertCount(1, $yamlMappings);
+ $this->assertStringEndsWith('CustomPathBundle/Resources/config/validation.yml', $yamlMappings[0]);
+ }
+
public function testValidationNoStaticMethod()
{
$container = $this->createContainerFromFile('validation_no_static_method');
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
- $this->assertCount(5, $calls);
+ $annotations = !class_exists(FullStack::class) && class_exists(Annotation::class);
+
+ $this->assertCount($annotations ? 6 : 5, $calls);
$this->assertSame('addXmlMappings', $calls[3][0]);
- $this->assertSame('setMetadataCache', $calls[4][0]);
- $this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[4][1]);
+ $i = 3;
+ if ($annotations) {
+ $this->assertSame('enableAnnotationMapping', $calls[++$i][0]);
+ }
+ $this->assertSame('setMetadataCache', $calls[++$i][0]);
+ $this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[$i][1]);
// no cache, no annotations, no static methods
}
+ public function testValidationMapping()
+ {
+ $container = $this->createContainerFromFile('validation_mapping');
+
+ $calls = $container->getDefinition('validator.builder')->getMethodCalls();
+
+ $this->assertSame('addXmlMappings', $calls[3][0]);
+ $this->assertCount(2, $calls[3][1][0]);
+
+ $this->assertSame('addYamlMappings', $calls[4][0]);
+ $this->assertCount(3, $calls[4][1][0]);
+ $this->assertContains('foo.yml', $calls[4][1][0][0]);
+ $this->assertContains('validation.yml', $calls[4][1][0][1]);
+ $this->assertContains('validation.yaml', $calls[4][1][0][2]);
+ }
+
public function testFormsCanBeEnabledWithoutCsrfProtection()
{
$container = $this->createContainerFromFile('form_no_csrf');
@@ -516,7 +690,7 @@ public function testStopwatchEnabledWithDebugModeDisabled()
public function testSerializerDisabled()
{
$container = $this->createContainerFromFile('default_config');
- $this->assertFalse($container->has('serializer'));
+ $this->assertSame(!class_exists(FullStack::class) && class_exists(Serializer::class), $container->has('serializer'));
}
public function testSerializerEnabled()
@@ -636,6 +810,28 @@ public function testDeprecatedSerializerCacheOption()
$this->assertEquals(new Reference('foo'), $cache);
}
+ public function testSerializerMapping()
+ {
+ $container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle', 'parent' => null))));
+ $configDir = __DIR__.'/Fixtures/TestBundle/Resources/config';
+ $expectedLoaders = array(
+ new Definition(AnnotationLoader::class, array(new Reference('annotation_reader'))),
+ new Definition(XmlFileLoader::class, array($configDir.'/serialization.xml')),
+ new Definition(YamlFileLoader::class, array($configDir.'/serialization.yml')),
+ new Definition(XmlFileLoader::class, array($configDir.'/serializer_mapping/files/foo.xml')),
+ new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/files/foo.yml')),
+ new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/serialization.yml')),
+ new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/serialization.yaml')),
+ );
+
+ foreach ($expectedLoaders as $definition) {
+ $definition->setPublic(false);
+ }
+
+ $loaders = $container->getDefinition('serializer.mapping.chain_loader')->getArgument(0);
+ $this->assertEquals(sort($expectedLoaders), sort($loaders));
+ }
+
public function testAssetHelperWhenAssetsAreEnabled()
{
$container = $this->createContainerFromFile('full');
@@ -692,6 +888,46 @@ public function testPropertyInfoEnabled()
$this->assertTrue($container->has('property_info'));
}
+ public function testEventDispatcherService()
+ {
+ $container = $this->createContainer(array('kernel.charset' => 'UTF-8', 'kernel.secret' => 'secret'));
+ $container->registerExtension(new FrameworkExtension());
+ $this->loadFromFile($container, 'default_config');
+ $container
+ ->register('foo', \stdClass::class)
+ ->setProperty('dispatcher', new Reference('event_dispatcher'));
+ $container->compile();
+ $this->assertInstanceOf(EventDispatcherInterface::class, $container->get('foo')->dispatcher);
+ }
+
+ public function testCacheDefaultRedisProvider()
+ {
+ $container = $this->createContainerFromFile('cache');
+
+ $redisUrl = 'redis://localhost';
+ $providerId = md5($redisUrl);
+
+ $this->assertTrue($container->hasDefinition($providerId));
+
+ $url = $container->getDefinition($providerId)->getArgument(0);
+
+ $this->assertSame($redisUrl, $url);
+ }
+
+ public function testCacheDefaultRedisProviderWithEnvVar()
+ {
+ $container = $this->createContainerFromFile('cache_env_var');
+
+ $redisUrl = 'redis://paas.com';
+ $providerId = md5($redisUrl);
+
+ $this->assertTrue($container->hasDefinition($providerId));
+
+ $url = $container->getDefinition($providerId)->getArgument(0);
+
+ $this->assertSame($redisUrl, $url);
+ }
+
public function testCachePoolServices()
{
$container = $this->createContainerFromFile('cache');
@@ -707,6 +943,7 @@ protected function createContainer(array $data = array())
{
return new ContainerBuilder(new ParameterBag(array_merge(array(
'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'),
+ 'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..', 'parent' => null)),
'kernel.cache_dir' => __DIR__,
'kernel.debug' => false,
'kernel.environment' => 'test',
@@ -730,6 +967,7 @@ protected function createContainerFromFile($file, $data = array(), $resetCompile
$container->getCompilerPassConfig()->setOptimizationPasses(array());
$container->getCompilerPassConfig()->setRemovingPasses(array());
}
+ $container->getCompilerPassConfig()->setBeforeRemovingPasses(array(new AddAnnotationsCachedReaderPass(), new AddConstraintValidatorsPass(), new TranslatorPass()));
$container->compile();
return self::$containerCache[$cacheKey] = $container;
@@ -749,14 +987,14 @@ protected function createContainerFromClosure($closure, $data = array())
return $container;
}
- private function assertPathPackage(ContainerBuilder $container, DefinitionDecorator $package, $basePath, $version, $format)
+ private function assertPathPackage(ContainerBuilder $container, ChildDefinition $package, $basePath, $version, $format)
{
$this->assertEquals('assets.path_package', $package->getParent());
$this->assertEquals($basePath, $package->getArgument(0));
$this->assertVersionStrategy($container, $package->getArgument(1), $version, $format);
}
- private function assertUrlPackage(ContainerBuilder $container, DefinitionDecorator $package, $baseUrls, $version, $format)
+ private function assertUrlPackage(ContainerBuilder $container, ChildDefinition $package, $baseUrls, $version, $format)
{
$this->assertEquals('assets.url_package', $package->getParent());
$this->assertEquals($baseUrls, $package->getArgument(0));
@@ -765,7 +1003,7 @@ private function assertUrlPackage(ContainerBuilder $container, DefinitionDecorat
private function assertVersionStrategy(ContainerBuilder $container, Reference $reference, $version, $format)
{
- $versionStrategy = $container->getDefinition($reference);
+ $versionStrategy = $container->getDefinition((string) $reference);
if (null === $version) {
$this->assertEquals('assets.empty_version_strategy', (string) $reference);
} else {
@@ -781,7 +1019,7 @@ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $con
$poolDefinition = $container->getDefinition($id);
- $this->assertInstanceOf(DefinitionDecorator::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache pool.', $id));
+ $this->assertInstanceOf(ChildDefinition::class, $poolDefinition, sprintf('Cache pool "%s" is based on an abstract cache pool.', $id));
$this->assertTrue($poolDefinition->hasTag('cache.pool'), sprintf('Service definition "%s" is tagged with the "cache.pool" tag.', $id));
$this->assertFalse($poolDefinition->isAbstract(), sprintf('Service definition "%s" is not abstract.', $id));
@@ -794,7 +1032,7 @@ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $con
do {
$parentId = $parentDefinition->getParent();
$parentDefinition = $container->findDefinition($parentId);
- } while ($parentDefinition instanceof DefinitionDecorator);
+ } while ($parentDefinition instanceof ChildDefinition);
switch ($adapter) {
case 'cache.adapter.apcu':
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.json
new file mode 100644
index 0000000000000..efcf34d06aa77
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.json
@@ -0,0 +1,20 @@
+[
+ {
+ "service": "service_1",
+ "public": true
+ },
+ {
+ "class": "Full\\Qualified\\Class1",
+ "public": true,
+ "synthetic": false,
+ "lazy": true,
+ "shared": true,
+ "abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
+ "file": null,
+ "factory_class": "Full\\Qualified\\FactoryClass",
+ "factory_method": "get",
+ "tags": []
+ }
+]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.md
new file mode 100644
index 0000000000000..ac56c0d4a4aff
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.md
@@ -0,0 +1,17 @@
+### alias_1
+
+- Service: `service_1`
+- Public: yes
+
+### service_1
+
+- Class: `Full\Qualified\Class1`
+- Public: yes
+- Synthetic: no
+- Lazy: yes
+- Shared: yes
+- Abstract: yes
+- Autowired: no
+- Autoconfigured: no
+- Factory Class: `Full\Qualified\FactoryClass`
+- Factory Method: `get`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.txt
new file mode 100644
index 0000000000000..75347e1a0e431
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.txt
@@ -0,0 +1,20 @@
+[39;49m // [39;49mThis service is an alias for the service [32mservice_1[39m
+
+[33mInformation for Service "[39m[32mservice_1[39m[33m"[39m
+[33m===================================[39m
+
+ ---------------- -----------------------------
+ [32m Option [39m [32m Value [39m
+ ---------------- -----------------------------
+ Service ID service_1
+ Class Full\Qualified\Class1
+ Tags -
+ Public yes
+ Synthetic no
+ Lazy yes
+ Shared yes
+ Abstract yes
+ Autowired no
+ Factory Class Full\Qualified\FactoryClass
+ Factory Method get
+ ---------------- -----------------------------
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.xml
new file mode 100644
index 0000000000000..19f5a04344fef
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_1.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json
new file mode 100644
index 0000000000000..03780e3eebe7a
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json
@@ -0,0 +1,41 @@
+[
+ {
+ "service": "service_2",
+ "public": false
+ },
+ {
+ "class": "Full\\Qualified\\Class2",
+ "public": false,
+ "synthetic": true,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "file": "\/path\/to\/file",
+ "factory_service": "factory.service",
+ "factory_method": "get",
+ "calls": [
+ "setMailer"
+ ],
+ "tags": [
+ {
+ "name": "tag1",
+ "parameters": {
+ "attr1": "val1",
+ "attr2": "val2"
+ }
+ },
+ {
+ "name": "tag1",
+ "parameters": {
+ "attr3": "val3"
+ }
+ },
+ {
+ "name": "tag2",
+ "parameters": []
+ }
+ ]
+ }
+]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md
new file mode 100644
index 0000000000000..406c5dcada7a4
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md
@@ -0,0 +1,25 @@
+### alias_2
+
+- Service: `service_2`
+- Public: no
+
+### service_2
+
+- Class: `Full\Qualified\Class2`
+- Public: no
+- Synthetic: yes
+- Lazy: no
+- Shared: yes
+- Abstract: no
+- Autowired: no
+- Autoconfigured: no
+- File: `/path/to/file`
+- Factory Service: `factory.service`
+- Factory Method: `get`
+- Call: `setMailer`
+- Tag: `tag1`
+ - Attr1: val1
+ - Attr2: val2
+- Tag: `tag1`
+ - Attr3: val3
+- Tag: `tag2`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt
new file mode 100644
index 0000000000000..4d11ab8eef220
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt
@@ -0,0 +1,24 @@
+[39;49m // [39;49mThis service is an alias for the service [32mservice_2[39m
+
+[33mInformation for Service "[39m[32mservice_2[39m[33m"[39m
+[33m===================================[39m
+
+ ----------------- ---------------------------------
+ [32m Option [39m [32m Value [39m
+ ----------------- ---------------------------------
+ Service ID service_2
+ Class Full\Qualified\Class2
+[39;49m Tags tag1 ([39;49m[32mattr1[39m[39;49m: val1, [39;49m[32mattr2[39m[39;49m: val2)[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mtag1 ([39;49m[32mattr3[39m[39;49m: val3)[39;49m[39;49m [39;49m
+[39;49m [39;49mtag2
+ Calls setMailer
+ Public no
+ Synthetic yes
+ Lazy no
+ Shared yes
+ Abstract no
+ Autowired no
+ Required File /path/to/file
+ Factory Service factory.service
+ Factory Method get
+ ----------------- ---------------------------------
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml
new file mode 100644
index 0000000000000..3c15460beebe8
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+ val1
+ val2
+
+
+ val3
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json
new file mode 100644
index 0000000000000..c304b33ac2283
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json
@@ -0,0 +1,91 @@
+{
+ "definitions": {
+ "definition_1": {
+ "class": "Full\\Qualified\\Class1",
+ "public": true,
+ "synthetic": false,
+ "lazy": true,
+ "shared": true,
+ "abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [
+ {
+ "type": "service",
+ "id": "definition2"
+ },
+ "%parameter%",
+ {
+ "class": "inline_service",
+ "public": true,
+ "synthetic": false,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [
+ "arg1",
+ "arg2"
+ ],
+ "file": null,
+ "tags": []
+ },
+ [
+ "foo",
+ {
+ "type": "service",
+ "id": "definition2"
+ },
+ {
+ "class": "inline_service",
+ "public": true,
+ "synthetic": false,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [],
+ "file": null,
+ "tags": []
+ }
+ ],
+ [
+ {
+ "type": "service",
+ "id": "definition_1"
+ },
+ {
+ "type": "service",
+ "id": "definition_2"
+ }
+ ],
+ [
+ {
+ "type": "service",
+ "id": "definition1"
+ },
+ "get"
+ ]
+ ],
+ "file": null,
+ "factory_class": "Full\\Qualified\\FactoryClass",
+ "factory_method": "get",
+ "tags": []
+ }
+ },
+ "aliases": {
+ "alias_1": {
+ "service": "service_1",
+ "public": true
+ },
+ "alias_2": {
+ "service": "service_2",
+ "public": false
+ }
+ },
+ "services": {
+ "service_container": "Symfony\\Component\\DependencyInjection\\ContainerBuilder"
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.md
new file mode 100644
index 0000000000000..29e34d2b0d94f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.md
@@ -0,0 +1,39 @@
+Public services
+===============
+
+Definitions
+-----------
+
+### definition_1
+
+- Class: `Full\Qualified\Class1`
+- Public: yes
+- Synthetic: no
+- Lazy: yes
+- Shared: yes
+- Abstract: yes
+- Autowired: no
+- Autoconfigured: no
+- Arguments: yes
+- Factory Class: `Full\Qualified\FactoryClass`
+- Factory Method: `get`
+
+
+Aliases
+-------
+
+### alias_1
+
+- Service: `service_1`
+- Public: yes
+
+### alias_2
+
+- Service: `service_2`
+- Public: no
+
+
+Services
+--------
+
+- `service_container`: `Symfony\Component\DependencyInjection\ContainerBuilder`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.txt
new file mode 100644
index 0000000000000..0e42596b99233
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.txt
@@ -0,0 +1,13 @@
+
+[33mSymfony Container Public Services[39m
+[33m=================================[39m
+
+ ------------------- --------------------------------------------------------
+ [32m Service ID [39m [32m Class name [39m
+ ------------------- --------------------------------------------------------
+ alias_1 alias for "service_1"
+ alias_2 alias for "service_2"
+ definition_1 Full\Qualified\Class1
+ service_container Symfony\Component\DependencyInjection\ContainerBuilder
+ ------------------- --------------------------------------------------------
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml
new file mode 100644
index 0000000000000..2d4de06aa84cb
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+ %parameter%
+
+
+ arg1
+ arg2
+
+
+
+ foo
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
index 170dfa2887e7c..7f86ccb2ac429 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
@@ -7,14 +7,12 @@
"lazy": true,
"shared": true,
"abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
"file": null,
"factory_class": "Full\\Qualified\\FactoryClass",
"factory_method": "get",
- "tags": [
-
- ],
- "autowire": false,
- "autowiring_types": []
+ "tags": []
}
},
"aliases": {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
index 279958648f9ac..aff2f08191d00 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
@@ -4,8 +4,7 @@ Public services
Definitions
-----------
-definition_1
-~~~~~~~~~~~~
+### definition_1
- Class: `Full\Qualified\Class1`
- Public: yes
@@ -14,6 +13,7 @@ definition_1
- Shared: yes
- Abstract: yes
- Autowired: no
+- Autoconfigured: no
- Factory Class: `Full\Qualified\FactoryClass`
- Factory Method: `get`
@@ -21,14 +21,12 @@ definition_1
Aliases
-------
-alias_1
-~~~~~~~
+### alias_1
- Service: `service_1`
- Public: yes
-alias_2
-~~~~~~~
+### alias_2
- Service: `service_2`
- Public: no
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
index 52031e59aa4ac..22a7fb4224127 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
index fe2b183901904..becd607b797a5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
@@ -7,14 +7,12 @@
"lazy": true,
"shared": true,
"abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
"file": null,
"factory_class": "Full\\Qualified\\FactoryClass",
"factory_method": "get",
- "tags": [
-
- ],
- "autowire": false,
- "autowiring_types": []
+ "tags": []
},
"definition_2": {
"class": "Full\\Qualified\\Class2",
@@ -23,9 +21,14 @@
"lazy": false,
"shared": true,
"abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
"file": "\/path\/to\/file",
"factory_service": "factory.service",
"factory_method": "get",
+ "calls": [
+ "setMailer"
+ ],
"tags": [
{
"name": "tag1",
@@ -42,16 +45,9 @@
},
{
"name": "tag2",
- "parameters": [
-
- ]
+ "parameters": []
}
- ],
- "calls": [
- "setMailer"
- ],
- "autowire": false,
- "autowiring_types": []
+ ]
}
},
"aliases": {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
index f1e22ddba499c..54655668b435b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
@@ -4,8 +4,7 @@ Public and private services
Definitions
-----------
-definition_1
-~~~~~~~~~~~~
+### definition_1
- Class: `Full\Qualified\Class1`
- Public: yes
@@ -14,11 +13,11 @@ definition_1
- Shared: yes
- Abstract: yes
- Autowired: no
+- Autoconfigured: no
- Factory Class: `Full\Qualified\FactoryClass`
- Factory Method: `get`
-definition_2
-~~~~~~~~~~~~
+### definition_2
- Class: `Full\Qualified\Class2`
- Public: no
@@ -27,6 +26,7 @@ definition_2
- Shared: yes
- Abstract: no
- Autowired: no
+- Autoconfigured: no
- File: `/path/to/file`
- Factory Service: `factory.service`
- Factory Method: `get`
@@ -42,14 +42,12 @@ definition_2
Aliases
-------
-alias_1
-~~~~~~~
+### alias_1
- Service: `service_1`
- Public: yes
-alias_2
-~~~~~~~
+### alias_2
- Service: `service_2`
- Public: no
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
index bde934fa50a39..54da4f4f48427 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
@@ -2,10 +2,10 @@
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
index a25a34b44a89d..fb9634f67a309 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
@@ -7,9 +7,14 @@
"lazy": false,
"shared": true,
"abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
"file": "\/path\/to\/file",
"factory_service": "factory.service",
"factory_method": "get",
+ "calls": [
+ "setMailer"
+ ],
"tags": [
{
"name": "tag1",
@@ -26,22 +31,11 @@
},
{
"name": "tag2",
- "parameters": [
-
- ]
+ "parameters": []
}
- ],
- "calls": [
- "setMailer"
- ],
- "autowire": false,
- "autowiring_types": []
+ ]
}
},
- "aliases": [
-
- ],
- "services": [
-
- ]
+ "aliases": [],
+ "services": []
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
index 8a9636f71db16..9895f1fb5d8b2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
@@ -4,8 +4,7 @@ Public and private services with tag `tag1`
Definitions
-----------
-definition_2
-~~~~~~~~~~~~
+### definition_2
- Class: `Full\Qualified\Class2`
- Public: no
@@ -14,6 +13,7 @@ definition_2
- Shared: yes
- Abstract: no
- Autowired: no
+- Autoconfigured: no
- File: `/path/to/file`
- Factory Service: `factory.service`
- Factory Method: `get`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
index d679db7b3b860..9c39b653dd5fc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
index 25138d78fd42c..7f49ac241ffde 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
@@ -7,14 +7,14 @@
"lazy": false,
"shared": true,
"abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
"file": "\/path\/to\/file",
- "calls": [
- "setMailer"
- ],
"factory_service": "factory.service",
"factory_method": "get",
- "autowire": false,
- "autowiring_types": []
+ "calls": [
+ "setMailer"
+ ]
}
],
"tag2": [
@@ -25,14 +25,14 @@
"lazy": false,
"shared": true,
"abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
"file": "\/path\/to\/file",
- "calls": [
- "setMailer"
- ],
"factory_service": "factory.service",
"factory_method": "get",
- "autowire": false,
- "autowiring_types": []
+ "calls": [
+ "setMailer"
+ ]
}
]
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
index 1731fc9f917ea..205596259d2c6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
@@ -4,8 +4,7 @@ Container tags
tag1
----
-definition_2
-~~~~~~~~~~~~
+### definition_2
- Class: `Full\Qualified\Class2`
- Public: no
@@ -14,6 +13,7 @@ definition_2
- Shared: yes
- Abstract: no
- Autowired: no
+- Autoconfigured: no
- File: `/path/to/file`
- Factory Service: `factory.service`
- Factory Method: `get`
@@ -23,8 +23,7 @@ definition_2
tag2
----
-definition_2
-~~~~~~~~~~~~
+### definition_2
- Class: `Full\Qualified\Class2`
- Public: no
@@ -33,6 +32,7 @@ definition_2
- Shared: yes
- Abstract: no
- Autowired: no
+- Autoconfigured: no
- File: `/path/to/file`
- Factory Service: `factory.service`
- Factory Method: `get`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
index 08352fa206877..4e98e77a19a23 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
@@ -1,7 +1,7 @@
-
+
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
index d11d6e92d49fc..940bab12699b1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
@@ -5,12 +5,10 @@
"lazy": true,
"shared": true,
"abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
"file": null,
"factory_class": "Full\\Qualified\\FactoryClass",
"factory_method": "get",
- "tags": [
-
- ],
- "autowire": false,
- "autowiring_types": []
+ "tags": []
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
index b1d46b69f4f9f..e4d0429b9087d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
@@ -5,5 +5,6 @@
- Shared: yes
- Abstract: yes
- Autowired: no
+- Autoconfigured: no
- Factory Class: `Full\Qualified\FactoryClass`
- Factory Method: `get`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
index f74cdbbccd5cc..596d918579071 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
@@ -1,17 +1,16 @@
- ------------------ -----------------------------
- [32m Option [39m [32m Value [39m
- ------------------ -----------------------------
- Service ID -
- Class Full\Qualified\Class1
- Tags -
- Public yes
- Synthetic no
- Lazy yes
- Shared yes
- Abstract yes
- Autowired no
- Autowiring Types -
- Factory Class Full\Qualified\FactoryClass
- Factory Method get
- ------------------ -----------------------------
+ ---------------- -----------------------------
+ [32m Option [39m [32m Value [39m
+ ---------------- -----------------------------
+ Service ID -
+ Class Full\Qualified\Class1
+ Tags -
+ Public yes
+ Synthetic no
+ Lazy yes
+ Shared yes
+ Abstract yes
+ Autowired no
+ Factory Class Full\Qualified\FactoryClass
+ Factory Method get
+ ---------------- -----------------------------
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
index 67d102945a6fe..d5015fdde3bd7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
index 8a6611a37cd7d..1c7b1ae14af42 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
@@ -5,9 +5,14 @@
"lazy": false,
"shared": true,
"abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
"file": "\/path\/to\/file",
"factory_service": "factory.service",
"factory_method": "get",
+ "calls": [
+ "setMailer"
+ ],
"tags": [
{
"name": "tag1",
@@ -24,14 +29,7 @@
},
{
"name": "tag2",
- "parameters": [
-
- ]
+ "parameters": []
}
- ],
- "calls": [
- "setMailer"
- ],
- "autowire": false,
- "autowiring_types": []
+ ]
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
index 1f097a2585321..6ff6d60b3dc93 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
@@ -5,6 +5,7 @@
- Shared: yes
- Abstract: no
- Autowired: no
+- Autoconfigured: no
- File: `/path/to/file`
- Factory Service: `factory.service`
- Factory Method: `get`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
index 86f44b3590946..a8ed854751b22 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
@@ -1,19 +1,20 @@
- ------------------ -------------------------------------------------------
- [32m Option [39m [32m Value [39m
- ------------------ -------------------------------------------------------
- Service ID -
- Class Full\Qualified\Class2
- Tags tag1 ([32mattr1[39m: val1, [32mattr2[39m: val2)tag1 ([32mattr3[39m: val3)tag2
- Calls setMailer
- Public no
- Synthetic yes
- Lazy no
- Shared yes
- Abstract no
- Autowired no
- Autowiring Types -
- Required File /path/to/file
- Factory Service factory.service
- Factory Method get
- ------------------ -------------------------------------------------------
+ ----------------- ---------------------------------
+ [32m Option [39m [32m Value [39m
+ ----------------- ---------------------------------
+ Service ID -
+ Class Full\Qualified\Class2
+[39;49m Tags tag1 ([39;49m[32mattr1[39m[39;49m: val1, [39;49m[32mattr2[39m[39;49m: val2)[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mtag1 ([39;49m[32mattr3[39m[39;49m: val3)[39;49m[39;49m [39;49m
+[39;49m [39;49mtag2
+ Calls setMailer
+ Public no
+ Synthetic yes
+ Lazy no
+ Shared yes
+ Abstract no
+ Autowired no
+ Required File /path/to/file
+ Factory Service factory.service
+ Factory Method get
+ ----------------- ---------------------------------
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
index 434a34b2565c4..72319eca97a4c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json
new file mode 100644
index 0000000000000..0590d3f76a611
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json
@@ -0,0 +1,74 @@
+{
+ "class": "Full\\Qualified\\Class1",
+ "public": true,
+ "synthetic": false,
+ "lazy": true,
+ "shared": true,
+ "abstract": true,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [
+ {
+ "type": "service",
+ "id": "definition2"
+ },
+ "%parameter%",
+ {
+ "class": "inline_service",
+ "public": true,
+ "synthetic": false,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [
+ "arg1",
+ "arg2"
+ ],
+ "file": null,
+ "tags": []
+ },
+ [
+ "foo",
+ {
+ "type": "service",
+ "id": "definition2"
+ },
+ {
+ "class": "inline_service",
+ "public": true,
+ "synthetic": false,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [],
+ "file": null,
+ "tags": []
+ }
+ ],
+ [
+ {
+ "type": "service",
+ "id": "definition_1"
+ },
+ {
+ "type": "service",
+ "id": "definition_2"
+ }
+ ],
+ [
+ {
+ "type": "service",
+ "id": "definition1"
+ },
+ "get"
+ ]
+ ],
+ "file": null,
+ "factory_class": "Full\\Qualified\\FactoryClass",
+ "factory_method": "get",
+ "tags": []
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.md
new file mode 100644
index 0000000000000..7cee17ad9cbb4
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.md
@@ -0,0 +1,11 @@
+- Class: `Full\Qualified\Class1`
+- Public: yes
+- Synthetic: no
+- Lazy: yes
+- Shared: yes
+- Abstract: yes
+- Autowired: no
+- Autoconfigured: no
+- Arguments: yes
+- Factory Class: `Full\Qualified\FactoryClass`
+- Factory Method: `get`
\ No newline at end of file
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt
new file mode 100644
index 0000000000000..c372da1d87298
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt
@@ -0,0 +1,22 @@
+ ---------------- -------------------------------------------
+ [32m Option [39m [32m Value [39m
+ ---------------- -------------------------------------------
+ Service ID -
+ Class Full\Qualified\Class1
+ Tags -
+ Public yes
+ Synthetic no
+ Lazy yes
+ Shared yes
+ Abstract yes
+ Autowired no
+ Factory Class Full\Qualified\FactoryClass
+ Factory Method get
+[39;49m Arguments Service(definition2)[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49m%parameter%[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mInlined Service[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mArray (3 element(s))[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mIterator (2 element(s))[39;49m[39;49m [39;49m
+[39;49m [39;49mClosureProxy(Service(definition1)::get())
+ ---------------- -------------------------------------------
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml
new file mode 100644
index 0000000000000..6d3cb8eea40be
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ %parameter%
+
+
+ arg1
+ arg2
+
+
+
+ foo
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json
new file mode 100644
index 0000000000000..8f65d27b83ea9
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json
@@ -0,0 +1,36 @@
+{
+ "class": "Full\\Qualified\\Class2",
+ "public": false,
+ "synthetic": true,
+ "lazy": false,
+ "shared": true,
+ "abstract": false,
+ "autowire": false,
+ "autoconfigure": false,
+ "arguments": [],
+ "file": "\/path\/to\/file",
+ "factory_service": "factory.service",
+ "factory_method": "get",
+ "calls": [
+ "setMailer"
+ ],
+ "tags": [
+ {
+ "name": "tag1",
+ "parameters": {
+ "attr1": "val1",
+ "attr2": "val2"
+ }
+ },
+ {
+ "name": "tag1",
+ "parameters": {
+ "attr3": "val3"
+ }
+ },
+ {
+ "name": "tag2",
+ "parameters": []
+ }
+ ]
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md
new file mode 100644
index 0000000000000..abe7dd475db2c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md
@@ -0,0 +1,19 @@
+- Class: `Full\Qualified\Class2`
+- Public: no
+- Synthetic: yes
+- Lazy: no
+- Shared: yes
+- Abstract: no
+- Autowired: no
+- Autoconfigured: no
+- Arguments: no
+- File: `/path/to/file`
+- Factory Service: `factory.service`
+- Factory Method: `get`
+- Call: `setMailer`
+- Tag: `tag1`
+ - Attr1: val1
+ - Attr2: val2
+- Tag: `tag1`
+ - Attr3: val3
+- Tag: `tag2`
\ No newline at end of file
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt
new file mode 100644
index 0000000000000..a8ed854751b22
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt
@@ -0,0 +1,20 @@
+ ----------------- ---------------------------------
+ [32m Option [39m [32m Value [39m
+ ----------------- ---------------------------------
+ Service ID -
+ Class Full\Qualified\Class2
+[39;49m Tags tag1 ([39;49m[32mattr1[39m[39;49m: val1, [39;49m[32mattr2[39m[39;49m: val2)[39;49m[39;49m [39;49m
+[39;49m [39;49m[39;49mtag1 ([39;49m[32mattr3[39m[39;49m: val3)[39;49m[39;49m [39;49m
+[39;49m [39;49mtag2
+ Calls setMailer
+ Public no
+ Synthetic yes
+ Lazy no
+ Shared yes
+ Abstract no
+ Autowired no
+ Required File /path/to/file
+ Factory Service factory.service
+ Factory Method get
+ ----------------- ---------------------------------
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml
new file mode 100644
index 0000000000000..72319eca97a4c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ val1
+ val2
+
+
+ val3
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt
index 587543fb0a47f..ed0bcca6562eb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt
@@ -11,7 +11,7 @@
| Requirements | name: [a-z]+ |
| Class | Symfony\Component\Routing\Route |
| Defaults | name: Joseph |
-| Options | compiler_class: Symfony\Component\Routing\RouteCompiler |
-| | opt1: val1 |
-| | opt2: val2 |
+[39;49m| Options | compiler_class: Symfony\Component\Routing\RouteCompiler[39;49m[39;49m |[39;49m
+[39;49m| | [39;49m[39;49mopt1: val1[39;49m[39;49m |[39;49m
+[39;49m| | [39;49mopt2: val2 |
+--------------+---------------------------------------------------------+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json
index d34b3a77aec6e..58caf26d537e7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.json
@@ -6,9 +6,7 @@
"scheme": "http|https",
"method": "PUT|POST",
"class": "Symfony\\Component\\Routing\\Route",
- "defaults": [
-
- ],
+ "defaults": [],
"requirements": "NO CUSTOM",
"options": {
"compiler_class": "Symfony\\Component\\Routing\\RouteCompiler",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt
index e75c19e13112c..828f6316bedb9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt
@@ -11,7 +11,7 @@
| Requirements | NO CUSTOM |
| Class | Symfony\Component\Routing\Route |
| Defaults | NONE |
-| Options | compiler_class: Symfony\Component\Routing\RouteCompiler |
-| | opt1: val1 |
-| | opt2: val2 |
+[39;49m| Options | compiler_class: Symfony\Component\Routing\RouteCompiler[39;49m[39;49m |[39;49m
+[39;49m| | [39;49m[39;49mopt1: val1[39;49m[39;49m |[39;49m
+[39;49m| | [39;49mopt2: val2 |
+--------------+---------------------------------------------------------+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json
index 7170953f5fee7..350bffdb3a9c7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json
@@ -27,9 +27,7 @@
"scheme": "http|https",
"method": "PUT|POST",
"class": "Symfony\\Component\\Routing\\Route",
- "defaults": [
-
- ],
+ "defaults": [],
"requirements": "NO CUSTOM",
"options": {
"compiler_class": "Symfony\\Component\\Routing\\RouteCompiler",
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 c0ae6ec5c6604..5a7cd354763d0 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
@@ -31,3 +31,19 @@
10,
array('%count%' => 10)
) ?>
+
+trans('other-domain-test-no-params-short-array', [], 'not_messages'); ?>
+
+trans('other-domain-test-no-params-long-array', array(), 'not_messages'); ?>
+
+trans('other-domain-test-params-short-array', ['foo' => 'bar'], 'not_messages'); ?>
+
+trans('other-domain-test-params-long-array', array('foo' => 'bar'), 'not_messages'); ?>
+
+transChoice('other-domain-test-trans-choice-short-array-%count%', 10, ['%count%' => 10], 'not_messages'); ?>
+
+transChoice('other-domain-test-trans-choice-long-array-%count%', 10, array('%count%' => 10), 'not_messages'); ?>
+
+trans('typecast', ['a' => (int) '123'], 'not_messages'); ?>
+transChoice('msg1', 10 + 1, [], 'not_messages'); ?>
+transChoice('msg2', ceil(4.5), [], 'not_messages'); ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php
new file mode 100644
index 0000000000000..a1ecee6d0b375
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php
@@ -0,0 +1,8 @@
+
-
-
+
+
other
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/SubCategory.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/SubCategory.php
new file mode 100644
index 0000000000000..7fc982b1df241
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/SubCategory.php
@@ -0,0 +1,13 @@
+ __DIR__.'/../Fixtures/Resources/views/this.is.a.template.format.engine',
+);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AnnotatedControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AnnotatedControllerTest.php
new file mode 100644
index 0000000000000..2fdbef8839496
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AnnotatedControllerTest.php
@@ -0,0 +1,39 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
+
+class AnnotatedControllerTest extends WebTestCase
+{
+ /**
+ * @dataProvider getRoutes
+ */
+ public function testAnnotatedController($path, $expectedValue)
+ {
+ $client = $this->createClient(array('test_case' => 'AnnotatedController', 'root_config' => 'config.yml'));
+ $client->request('GET', '/annotated'.$path);
+
+ $this->assertSame(200, $client->getResponse()->getStatusCode());
+ $this->assertSame($expectedValue, $client->getResponse()->getContent());
+ }
+
+ public function getRoutes()
+ {
+ return array(
+ array('/null_request', 'Symfony\Component\HttpFoundation\Request'),
+ array('/null_argument', ''),
+ array('/null_argument_with_route_param', ''),
+ array('/null_argument_with_route_param/value', 'value'),
+ array('/argument_with_route_param_and_default', 'value'),
+ array('/argument_with_route_param_and_default/custom', 'custom'),
+ );
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php
index 52b8c8cdcf521..fa92514a9c14c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php
@@ -13,7 +13,10 @@
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface;
+use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
+use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundleEngineInterface;
class AutowiringTypesTest extends WebTestCase
@@ -46,6 +49,30 @@ public function testTemplatingAutowiring()
$this->assertInstanceOf(ComponentEngineInterface::class, $autowiredServices->getEngine());
}
+ public function testEventDispatcherAutowiring()
+ {
+ static::bootKernel(array('debug' => false));
+ $container = static::$kernel->getContainer();
+
+ $autowiredServices = $container->get('test.autowiring_types.autowired_services');
+ $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled');
+
+ static::bootKernel(array('debug' => true));
+ $container = static::$kernel->getContainer();
+
+ $autowiredServices = $container->get('test.autowiring_types.autowired_services');
+ $this->assertInstanceOf(TraceableEventDispatcher::class, $autowiredServices->getDispatcher(), 'The debug.event_dispatcher service should be injected if the debug is enabled');
+ }
+
+ public function testCacheAutowiring()
+ {
+ static::bootKernel();
+ $container = static::$kernel->getContainer();
+
+ $autowiredServices = $container->get('test.autowiring_types.autowired_services');
+ $this->assertInstanceOf(FilesystemAdapter::class, $autowiredServices->getCachePool());
+ }
+
protected static function createKernel(array $options = array())
{
return parent::createKernel(array('test_case' => 'AutowiringTypes') + $options);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php
index 0636d591e5677..7168e4902c53b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/AutowiringTypes/AutowiredServices.php
@@ -12,20 +12,26 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\AutowiringTypes;
use Doctrine\Common\Annotations\Reader;
+use Psr\Cache\CacheItemPoolInterface;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundleEngineInterface;
use Symfony\Component\Templating\EngineInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class AutowiredServices
{
private $annotationReader;
private $frameworkBundleEngine;
private $engine;
+ private $dispatcher;
+ private $cachePool;
- public function __construct(Reader $annotationReader = null, FrameworkBundleEngineInterface $frameworkBundleEngine, EngineInterface $engine)
+ public function __construct(Reader $annotationReader = null, FrameworkBundleEngineInterface $frameworkBundleEngine, EngineInterface $engine, EventDispatcherInterface $dispatcher, CacheItemPoolInterface $cachePool)
{
$this->annotationReader = $annotationReader;
$this->frameworkBundleEngine = $frameworkBundleEngine;
$this->engine = $engine;
+ $this->dispatcher = $dispatcher;
+ $this->cachePool = $cachePool;
}
public function getAnnotationReader()
@@ -42,4 +48,14 @@ public function getEngine()
{
return $this->engine;
}
+
+ public function getDispatcher()
+ {
+ return $this->dispatcher;
+ }
+
+ public function getCachePool()
+ {
+ return $this->cachePool;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/AnnotatedController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/AnnotatedController.php
new file mode 100644
index 0000000000000..98a3ace982e33
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/AnnotatedController.php
@@ -0,0 +1,51 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Annotation\Route;
+
+class AnnotatedController
+{
+ /**
+ * @Route("/null_request", name="null_request")
+ */
+ public function requestDefaultNullAction(Request $request = null)
+ {
+ return new Response($request ? get_class($request) : null);
+ }
+
+ /**
+ * @Route("/null_argument", name="null_argument")
+ */
+ public function argumentDefaultNullWithoutRouteParamAction($value = null)
+ {
+ return new Response($value);
+ }
+
+ /**
+ * @Route("/null_argument_with_route_param/{value}", name="null_argument_with_route_param")
+ */
+ public function argumentDefaultNullWithRouteParamAction($value = null)
+ {
+ return new Response($value);
+ }
+
+ /**
+ * @Route("/argument_with_route_param_and_default/{value}", defaults={"value": "value"}, name="argument_with_route_param_and_default")
+ */
+ public function argumentWithoutDefaultWithRouteParamAndDefaultAction($value)
+ {
+ return new Response($value);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php
new file mode 100644
index 0000000000000..2de08632fa144
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/AnnotationReaderPass.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+class AnnotationReaderPass implements CompilerPassInterface
+{
+ public function process(ContainerBuilder $container)
+ {
+ // simulate using "annotation_reader" in a compiler pass
+ $container->get('annotation_reader');
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/Config/CustomConfig.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/Config/CustomConfig.php
index 8b4abb7a08d6b..d3a9b2a1b88e2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/Config/CustomConfig.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/DependencyInjection/Config/CustomConfig.php
@@ -18,6 +18,13 @@ public function addConfiguration($rootNode)
$rootNode
->children()
->scalarNode('custom')->end()
+ ->arrayNode('array')
+ ->children()
+ ->scalarNode('child1')->end()
+ ->scalarNode('child2')->end()
+ ->end()
+ ->end()
+ ->end()
->end()
;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestBundle.php
index e7982cfaab7cc..d63658bacf021 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestBundle.php
@@ -13,6 +13,7 @@
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\AnnotationReaderPass;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\Config\CustomConfig;
class TestBundle extends Bundle
@@ -25,5 +26,7 @@ public function build(ContainerBuilder $container)
$extension = $container->getExtension('test');
$extension->setCustomConfig(new CustomConfig());
+
+ $container->addCompilerPass(new AnnotationReaderPass());
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php
new file mode 100644
index 0000000000000..59949dfdfda9b
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php
@@ -0,0 +1,86 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
+
+use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand;
+use Symfony\Component\Console\Tester\CommandTester;
+
+/**
+ * @group functional
+ */
+class CachePoolClearCommandTest extends WebTestCase
+{
+ private $application;
+
+ protected function setUp()
+ {
+ static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml'));
+ }
+
+ public function testClearPrivatePool()
+ {
+ $tester = $this->createCommandTester();
+ $tester->execute(array('pools' => array('cache.private_pool')), array('decorated' => false));
+
+ $this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
+ $this->assertContains('Clearing cache pool: cache.private_pool', $tester->getDisplay());
+ $this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
+ }
+
+ public function testClearPublicPool()
+ {
+ $tester = $this->createCommandTester();
+ $tester->execute(array('pools' => array('cache.public_pool')), array('decorated' => false));
+
+ $this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
+ $this->assertContains('Clearing cache pool: cache.public_pool', $tester->getDisplay());
+ $this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
+ }
+
+ public function testClearPoolWithCustomClearer()
+ {
+ $tester = $this->createCommandTester();
+ $tester->execute(array('pools' => array('cache.pool_with_clearer')), array('decorated' => false));
+
+ $this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
+ $this->assertContains('Clearing cache pool: cache.pool_with_clearer', $tester->getDisplay());
+ $this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
+ }
+
+ public function testCallClearer()
+ {
+ $tester = $this->createCommandTester();
+ $tester->execute(array('pools' => array('cache.default_clearer')), array('decorated' => false));
+
+ $this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success');
+ $this->assertContains('Calling cache clearer: cache.default_clearer', $tester->getDisplay());
+ $this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
+ * @expectedExceptionMessage You have requested a non-existent service "unknown_pool"
+ */
+ public function testClearUnexistingPool()
+ {
+ $this->createCommandTester()
+ ->execute(array('pools' => array('unknown_pool')), array('decorated' => false));
+ }
+
+ private function createCommandTester()
+ {
+ $command = new CachePoolClearCommand();
+ $command->setContainer(static::$kernel->getContainer());
+
+ return new CommandTester($command);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php
index 2318c2da6244c..06ed75d64d5c1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php
@@ -17,16 +17,6 @@
class CachePoolsTest extends WebTestCase
{
- protected function setUp()
- {
- $_SERVER['SYMFONY__REDIS_HOST'] = getenv('REDIS_HOST');
- }
-
- protected function tearDown()
- {
- unset($_SERVER['SYMFONY__REDIS_HOST']);
- }
-
public function testCachePools()
{
$this->doTestCachePools(array(), FilesystemAdapter::class);
@@ -39,6 +29,11 @@ public function testRedisCachePools()
{
try {
$this->doTestCachePools(array('root_config' => 'redis_config.yml', 'environment' => 'redis_cache'), RedisAdapter::class);
+ } catch (\PHPUnit\Framework\Error\Warning $e) {
+ if (0 !== strpos($e->getMessage(), 'unable to connect to')) {
+ throw $e;
+ }
+ $this->markTestSkipped($e->getMessage());
} catch (\PHPUnit_Framework_Error_Warning $e) {
if (0 !== strpos($e->getMessage(), 'unable to connect to')) {
throw $e;
@@ -59,6 +54,11 @@ public function testRedisCustomCachePools()
{
try {
$this->doTestCachePools(array('root_config' => 'redis_custom_config.yml', 'environment' => 'custom_redis_cache'), RedisAdapter::class);
+ } catch (\PHPUnit\Framework\Error\Warning $e) {
+ if (0 !== strpos($e->getMessage(), 'unable to connect to')) {
+ throw $e;
+ }
+ $this->markTestSkipped($e->getMessage());
} catch (\PHPUnit_Framework_Error_Warning $e) {
if (0 !== strpos($e->getMessage(), 'unable to connect to')) {
throw $e;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
index 0305d65f6f3c5..5b40325e08eb9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php
@@ -48,6 +48,16 @@ public function testDumpBundleOption()
$this->assertContains('foo', $tester->getDisplay());
}
+ public function testParametersValuesAreResolved()
+ {
+ $tester = $this->createCommandTester();
+ $ret = $tester->execute(array('name' => 'framework'));
+
+ $this->assertSame(0, $ret, 'Returns 0 in case of success');
+ $this->assertContains("locale: '%env(LOCALE)%'", $tester->getDisplay());
+ $this->assertContains('secret: test', $tester->getDisplay());
+ }
+
public function testDumpUndefinedBundleOption()
{
$tester = $this->createCommandTester();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php
index b0ac90c31f5f7..3817afed170c3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php
@@ -40,6 +40,39 @@ public function testDumpBundleName()
$this->assertContains(' custom:', $tester->getDisplay());
}
+ public function testDumpAtPath()
+ {
+ $tester = $this->createCommandTester();
+ $ret = $tester->execute(array(
+ 'name' => 'test',
+ 'path' => 'array',
+ ));
+
+ $this->assertSame(0, $ret, 'Returns 0 in case of success');
+ $this->assertSame(<<<'EOL'
+# Default configuration for extension with alias: "test" at path "array"
+array:
+ child1: ~
+ child2: ~
+
+
+EOL
+ , $tester->getDisplay(true));
+ }
+
+ public function testDumpAtPathXml()
+ {
+ $tester = $this->createCommandTester();
+ $ret = $tester->execute(array(
+ 'name' => 'test',
+ 'path' => 'array',
+ '--format' => 'xml',
+ ));
+
+ $this->assertSame(1, $ret);
+ $this->assertContains('[ERROR] The "path" option is only available for the "yaml" format.', $tester->getDisplay());
+ }
+
/**
* @return CommandTester
*/
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php
new file mode 100644
index 0000000000000..c02a6b84e519c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
+
+use Symfony\Component\PropertyInfo\Type;
+
+class PropertyInfoTest extends WebTestCase
+{
+ public function testPhpDocPriority()
+ {
+ static::bootKernel(array('test_case' => 'Serializer'));
+ $container = static::$kernel->getContainer();
+
+ $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))), $container->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes'));
+ }
+}
+
+class Dummy
+{
+ /**
+ * @param int[] $codes
+ */
+ public function setCodes(array $codes)
+ {
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php
index 415e031189c3a..166d8a33919df 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php
@@ -134,18 +134,4 @@ public function getConfigs()
array('config.yml', false),
);
}
-
- protected function setUp()
- {
- parent::setUp();
-
- $this->deleteTmpDir('SessionTest');
- }
-
- protected function tearDown()
- {
- parent::tearDown();
-
- $this->deleteTmpDir('SessionTest');
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php
index 50d4cfa4db269..2861297fe0256 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php
@@ -13,7 +13,6 @@
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase;
use Symfony\Component\Filesystem\Filesystem;
-use Symfony\Component\HttpKernel\Kernel;
class WebTestCase extends BaseWebTestCase
{
@@ -23,9 +22,19 @@ public static function assertRedirect($response, $location)
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
}
- protected function deleteTmpDir($testCase)
+ public static function setUpBeforeClass()
{
- if (!file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) {
+ static::deleteTmpDir();
+ }
+
+ public static function tearDownAfterClass()
+ {
+ static::deleteTmpDir();
+ }
+
+ protected static function deleteTmpDir()
+ {
+ if (!file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) {
return;
}
@@ -49,10 +58,16 @@ protected static function createKernel(array $options = array())
}
return new $class(
+ static::getVarDir(),
$options['test_case'],
isset($options['root_config']) ? $options['root_config'] : 'config.yml',
- isset($options['environment']) ? $options['environment'] : 'frameworkbundletest'.strtolower($options['test_case']),
+ isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']),
isset($options['debug']) ? $options['debug'] : true
);
}
+
+ protected static function getVarDir()
+ {
+ return substr(strrchr(get_called_class(), '\\'), 1);
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php
new file mode 100644
index 0000000000000..f3290d7728541
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
+use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
+use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
+
+return array(
+ new FrameworkBundle(),
+ new TestBundle(),
+ new SensioFrameworkExtraBundle(),
+);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/config.yml
new file mode 100644
index 0000000000000..377d3e7852064
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/config.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ../config/default.yml }
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/routing.yml
new file mode 100644
index 0000000000000..ebd18a0a4c282
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/routing.yml
@@ -0,0 +1,4 @@
+annotated_controller:
+ prefix: /annotated
+ resource: "@TestBundle/Controller/AnnotatedController.php"
+ type: annotation
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php
index b07d44fe22be5..58fb963855e2f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php
@@ -11,30 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app;
-// get the autoload file
-$dir = __DIR__;
-$lastDir = null;
-while ($dir !== $lastDir) {
- $lastDir = $dir;
-
- if (file_exists($dir.'/autoload.php')) {
- require_once $dir.'/autoload.php';
- break;
- }
-
- if (file_exists($dir.'/autoload.php.dist')) {
- require_once $dir.'/autoload.php.dist';
- break;
- }
-
- if (file_exists($dir.'/vendor/autoload.php')) {
- require_once $dir.'/vendor/autoload.php';
- break;
- }
-
- $dir = dirname($dir);
-}
-
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Kernel;
@@ -46,14 +22,16 @@
*/
class AppKernel extends Kernel
{
+ private $varDir;
private $testCase;
private $rootConfig;
- public function __construct($testCase, $rootConfig, $environment, $debug)
+ public function __construct($varDir, $testCase, $rootConfig, $environment, $debug)
{
if (!is_dir(__DIR__.'/'.$testCase)) {
throw new \InvalidArgumentException(sprintf('The test case "%s" does not exist.', $testCase));
}
+ $this->varDir = $varDir;
$this->testCase = $testCase;
$fs = new Filesystem();
@@ -81,12 +59,12 @@ public function getRootDir()
public function getCacheDir()
{
- return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/cache/'.$this->environment;
+ return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/cache/'.$this->environment;
}
public function getLogDir()
{
- return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/logs';
+ return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
@@ -96,13 +74,13 @@ public function registerContainerConfiguration(LoaderInterface $loader)
public function serialize()
{
- return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
+ return serialize(array($this->varDir, $this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
}
public function unserialize($str)
{
$a = unserialize($str);
- $this->__construct($a[0], $a[1], $a[2], $a[3]);
+ $this->__construct($a[0], $a[1], $a[2], $a[3], $a[4]);
}
protected function getKernelParameters()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/bundles.php
new file mode 100644
index 0000000000000..a73987bcc986a
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/bundles.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
+use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
+
+return array(
+ new FrameworkBundle(),
+ new TestBundle(),
+);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml
new file mode 100644
index 0000000000000..75107485ee65f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml
@@ -0,0 +1,21 @@
+imports:
+ - { resource: ../config/default.yml }
+
+services:
+ dummy:
+ class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass
+ arguments: ['@cache.private_pool']
+ custom_clearer:
+ parent: cache.default_clearer
+ tags:
+ - name: kernel.cache_clearer
+
+framework:
+ cache:
+ pools:
+ cache.private_pool: ~
+ cache.public_pool:
+ public: true
+ cache.pool_with_clearer:
+ public: true
+ clearer: custom_clearer
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml
index 2794a72c809d9..02de40c5b81e5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml
@@ -1,10 +1,13 @@
imports:
- { resource: ../config/default.yml }
+parameters:
+ env(REDIS_HOST): 'localhost'
+
framework:
cache:
app: cache.adapter.redis
- default_redis_provider: "redis://%redis_host%"
+ default_redis_provider: "redis://%env(REDIS_HOST)%"
pools:
cache.pool1:
public: true
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml
index 70a51b272e5a4..9206638495947 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml
@@ -1,12 +1,15 @@
imports:
- { resource: ../config/default.yml }
+parameters:
+ env(REDIS_HOST): 'localhost'
+
services:
cache.test_redis_connection:
public: false
class: Redis
calls:
- - [connect, ['%redis_host%']]
+ - [connect, ['%env(REDIS_HOST)%']]
cache.app:
parent: cache.adapter.redis
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml
index 377d3e7852064..c1d1288046050 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml
@@ -1,2 +1,10 @@
imports:
- { resource: ../config/default.yml }
+
+framework:
+ secret: '%secret%'
+ default_locale: '%env(LOCALE)%'
+
+parameters:
+ env(LOCALE): en
+ secret: test
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
index 63d5b2dcb96aa..5fde7f27f8c42 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
-class MicroKernelTraitTest extends \PHPUnit_Framework_TestCase
+class MicroKernelTraitTest extends TestCase
{
public function test()
{
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php
index 3c8670df4414e..407158333d89e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php
@@ -2,11 +2,12 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
-class DelegatingLoaderTest extends \PHPUnit_Framework_TestCase
+class DelegatingLoaderTest extends TestCase
{
public function testConstructorApi()
{
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
index 057aa6c8091a4..fb5395ea6d26d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher;
use Symfony\Component\Routing\RequestContext;
-class RedirectableUrlMatcherTest extends \PHPUnit_Framework_TestCase
+class RedirectableUrlMatcherTest extends TestCase
{
public function testRedirectWhenNoSlash()
{
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php
index 4727fc4b82f53..2876d5d735815 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php
@@ -11,11 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
+use Symfony\Component\DependencyInjection\Config\ContainerParametersResource;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
-class RouterTest extends \PHPUnit_Framework_TestCase
+class RouterTest extends TestCase
{
public function testGenerateWithServiceParam()
{
@@ -216,6 +218,20 @@ public function testDefaultValuesAsNonStrings($value)
$this->assertSame($value, $route->getDefault('foo'));
}
+ public function testGetRouteCollectionAddsContainerParametersResource()
+ {
+ $routeCollection = $this->getMockBuilder(RouteCollection::class)->getMock();
+ $routeCollection->method('getIterator')->willReturn(new \ArrayIterator(array(new Route('/%locale%'))));
+ $routeCollection->expects($this->once())->method('addResource')->with(new ContainerParametersResource(array('locale' => 'en')));
+
+ $sc = $this->getServiceContainer($routeCollection);
+ $sc->setParameter('locale', 'en');
+
+ $router = new Router($sc, 'foo');
+
+ $router->getRouteCollection();
+ }
+
public function getNonStringValues()
{
return array(array(null), array(false), array(true), array(new \stdClass()), array(array('foo', 'bar')), array(array(array())));
@@ -228,7 +244,7 @@ public function getNonStringValues()
*/
private function getServiceContainer(RouteCollection $routes)
{
- $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
+ $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
$loader
->expects($this->any())
@@ -236,7 +252,7 @@ private function getServiceContainer(RouteCollection $routes)
->will($this->returnValue($routes))
;
- $sc = $this->getMock('Symfony\\Component\\DependencyInjection\\Container', array('get'));
+ $sc = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Container')->setMethods(array('get'))->getMock();
$sc
->expects($this->once())
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/DelegatingEngineTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/DelegatingEngineTest.php
index 4eaafddfa4c68..e3ff92b874c08 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/DelegatingEngineTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/DelegatingEngineTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\DelegatingEngine;
use Symfony\Component\HttpFoundation\Response;
-class DelegatingEngineTest extends \PHPUnit_Framework_TestCase
+class DelegatingEngineTest extends TestCase
{
public function testSupportsRetrievesEngineFromTheContainer()
{
@@ -85,7 +86,7 @@ public function testRenderResponseWithTemplatingEngine()
private function getEngineMock($template, $supports)
{
- $engine = $this->getMock('Symfony\Component\Templating\EngineInterface');
+ $engine = $this->getMockBuilder('Symfony\Component\Templating\EngineInterface')->getMock();
$engine->expects($this->once())
->method('supports')
@@ -97,7 +98,7 @@ private function getEngineMock($template, $supports)
private function getFrameworkEngineMock($template, $supports)
{
- $engine = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface');
+ $engine = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
$engine->expects($this->once())
->method('supports')
@@ -109,7 +110,7 @@ private function getFrameworkEngineMock($template, $supports)
private function getContainerMock($services)
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$i = 0;
foreach ($services as $id => $service) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/GlobalVariablesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/GlobalVariablesTest.php
index 5c00c62e7ff9d..348820b321225 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/GlobalVariablesTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/GlobalVariablesTest.php
@@ -26,6 +26,32 @@ protected function setUp()
$this->globals = new GlobalVariables($this->container);
}
+ public function testGetTokenNoTokenStorage()
+ {
+ $this->assertNull($this->globals->getToken());
+ }
+
+ public function testGetTokenNoToken()
+ {
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
+ $this->container->set('security.token_storage', $tokenStorage);
+ $this->assertNull($this->globals->getToken());
+ }
+
+ public function testGetToken()
+ {
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
+
+ $this->container->set('security.token_storage', $tokenStorage);
+
+ $tokenStorage
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue('token'));
+
+ $this->assertSame('token', $this->globals->getToken());
+ }
+
public function testGetUserNoTokenStorage()
{
$this->assertNull($this->globals->getUser());
@@ -33,7 +59,7 @@ public function testGetUserNoTokenStorage()
public function testGetUserNoToken()
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->container->set('security.token_storage', $tokenStorage);
$this->assertNull($this->globals->getUser());
}
@@ -43,8 +69,8 @@ public function testGetUserNoToken()
*/
public function testGetUser($user, $expectedUser)
{
- $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
- $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
+ $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$this->container->set('security.token_storage', $tokenStorage);
@@ -63,9 +89,9 @@ public function testGetUser($user, $expectedUser)
public function getUserProvider()
{
- $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$std = new \stdClass();
- $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
return array(
array($user, $user),
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/AssetsHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/AssetsHelperTest.php
index 659f463adbce3..01fac959db90b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/AssetsHelperTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/AssetsHelperTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\AssetsHelper;
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\Packages;
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
-class AssetsHelperTest extends \PHPUnit_Framework_TestCase
+class AssetsHelperTest extends TestCase
{
private $helper;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php
index d626e63e41cfa..4ece72e47e125 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php
@@ -11,11 +11,12 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\RequestHelper;
-class RequestHelperTest extends \PHPUnit_Framework_TestCase
+class RequestHelperTest extends TestCase
{
protected $requestStack;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php
index 5517afdb732fd..f664a49b12eec 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\SessionHelper;
-class SessionHelperTest extends \PHPUnit_Framework_TestCase
+class SessionHelperTest extends TestCase
{
protected $requestStack;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php
index 1a0ff5f548cee..686c655aac8f2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/StopwatchHelperTest.php
@@ -11,13 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\StopwatchHelper;
-class StopwatchHelperTest extends \PHPUnit_Framework_TestCase
+class StopwatchHelperTest extends TestCase
{
public function testDevEnvironment()
{
- $stopwatch = $this->getMock('Symfony\Component\Stopwatch\Stopwatch');
+ $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')->getMock();
$stopwatch->expects($this->once())
->method('start')
->with('foo');
@@ -29,11 +30,10 @@ public function testDevEnvironment()
public function testProdEnvironment()
{
$helper = new StopwatchHelper(null);
+ $helper->start('foo');
- try {
- $helper->start('foo');
- } catch (\BadMethodCallException $e) {
- $this->fail('Assumed stopwatch is not called when not provided');
- }
+ // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
+ // can be executed without throwing any exceptions
+ $this->addToAssertionCount(1);
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Loader/TemplateLocatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Loader/TemplateLocatorTest.php
index f680db942b2bd..96d75e3c3e0c0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Loader/TemplateLocatorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Loader/TemplateLocatorTest.php
@@ -38,6 +38,17 @@ public function testLocateATemplate()
$this->assertEquals('/path/to/template', $locator->locate($template));
}
+ public function testLocateATemplateFromCacheDir()
+ {
+ $template = new TemplateReference('bundle', 'controller', 'name', 'format', 'engine');
+
+ $fileLocator = $this->getFileLocator();
+
+ $locator = new TemplateLocator($fileLocator, __DIR__.'/../../Fixtures');
+
+ $this->assertEquals(realpath(__DIR__.'/../../Fixtures/Resources/views/this.is.a.template.format.engine'), $locator->locate($template));
+ }
+
public function testThrowsExceptionWhenTemplateNotFound()
{
$template = new TemplateReference('bundle', 'controller', 'name', 'format', 'engine');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/PhpEngineTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/PhpEngineTest.php
index b5eeb901342db..2cf3d4a18d1bb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/PhpEngineTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/PhpEngineTest.php
@@ -38,8 +38,7 @@ public function testEvaluateWithoutAvailableRequest()
$loader = $this->getMockForAbstractClass('Symfony\Component\Templating\Loader\Loader');
$engine = new PhpEngine(new TemplateNameParser(), $container, $loader, new GlobalVariables($container));
- $container->set('request_stack', null);
-
+ $this->assertFalse($container->has('request_stack'));
$globals = $engine->getGlobals();
$this->assertEmpty($globals['app']->getRequest());
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php
index 9c19087264425..3e162d167d23e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php
@@ -22,7 +22,7 @@ class TemplateNameParserTest extends TestCase
protected function setUp()
{
- $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundle')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php
index c49010bfdc357..1f6f51dd3351d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateTest.php
@@ -19,21 +19,9 @@ class TemplateTest extends TestCase
/**
* @dataProvider getTemplateToPathProvider
*/
- public function testGetPathForTemplatesInABundle($template, $path)
+ public function testGetPathForTemplate($template, $path)
{
- if ($template->get('bundle')) {
- $this->assertEquals($template->getPath(), $path);
- }
- }
-
- /**
- * @dataProvider getTemplateToPathProvider
- */
- public function testGetPathForTemplatesOutOfABundle($template, $path)
- {
- if (!$template->get('bundle')) {
- $this->assertEquals($template->getPath(), $path);
- }
+ $this->assertSame($template->getPath(), $path);
}
public function getTemplateToPathProvider()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
index 9411c1cb4718d..ef01f0e3b815f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
@@ -44,7 +44,7 @@ public function testThatRenderLogsTime()
*/
private function getContainer()
{
- return $this->getMock('Symfony\Component\DependencyInjection\Container');
+ return $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')->getMock();
}
/**
@@ -52,8 +52,8 @@ private function getContainer()
*/
private function getTemplateNameParser()
{
- $templateReference = $this->getMock('Symfony\Component\Templating\TemplateReferenceInterface');
- $templateNameParser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface');
+ $templateReference = $this->getMockBuilder('Symfony\Component\Templating\TemplateReferenceInterface')->getMock();
+ $templateNameParser = $this->getMockBuilder('Symfony\Component\Templating\TemplateNameParserInterface')->getMock();
$templateNameParser->expects($this->any())
->method('parse')
->will($this->returnValue($templateReference));
@@ -111,6 +111,6 @@ private function getStopwatchEvent()
*/
private function getStopwatch()
{
- return $this->getMock('Symfony\Component\Stopwatch\Stopwatch');
+ return $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')->getMock();
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/TestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/TestCase.php
index 8e724305a298a..115ca1ae58a29 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/TestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/TestCase.php
@@ -11,6 +11,8 @@
namespace Symfony\Bundle\FrameworkBundle\Tests;
-class TestCase extends \PHPUnit_Framework_TestCase
+use PHPUnit\Framework\TestCase as PHPUnitTestCase;
+
+class TestCase extends PHPUnitTestCase
{
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php
index 420d2f2d71dd3..e8c56ee4d5e52 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php
@@ -39,18 +39,31 @@ public function testExtraction($resource)
nowdoc key with whitespace and nonescaped \$\n sequences
EOF;
// Assert
- $expectedCatalogue = array('messages' => array(
- 'single-quoted key' => 'prefixsingle-quoted key',
- 'double-quoted key' => 'prefixdouble-quoted key',
- 'heredoc key' => 'prefixheredoc key',
- 'nowdoc key' => 'prefixnowdoc key',
- "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences",
- 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences',
- 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"',
- $expectedHeredoc => 'prefix'.$expectedHeredoc,
- $expectedNowdoc => 'prefix'.$expectedNowdoc,
- '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
- ));
+ $expectedCatalogue = array(
+ 'messages' => array(
+ 'single-quoted key' => 'prefixsingle-quoted key',
+ 'double-quoted key' => 'prefixdouble-quoted key',
+ 'heredoc key' => 'prefixheredoc key',
+ 'nowdoc key' => 'prefixnowdoc key',
+ "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences",
+ 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences',
+ 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"',
+ $expectedHeredoc => 'prefix'.$expectedHeredoc,
+ $expectedNowdoc => 'prefix'.$expectedNowdoc,
+ '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
+ ),
+ 'not_messages' => array(
+ 'other-domain-test-no-params-short-array' => 'prefixother-domain-test-no-params-short-array',
+ 'other-domain-test-no-params-long-array' => 'prefixother-domain-test-no-params-long-array',
+ 'other-domain-test-params-short-array' => 'prefixother-domain-test-params-short-array',
+ 'other-domain-test-params-long-array' => 'prefixother-domain-test-params-long-array',
+ 'other-domain-test-trans-choice-short-array-%count%' => 'prefixother-domain-test-trans-choice-short-array-%count%',
+ 'other-domain-test-trans-choice-long-array-%count%' => 'prefixother-domain-test-trans-choice-long-array-%count%',
+ 'typecast' => 'prefixtypecast',
+ 'msg1' => 'prefixmsg1',
+ 'msg2' => 'prefixmsg2',
+ ),
+ );
$actualCatalogue = $catalogue->all();
$this->assertEquals($expectedCatalogue, $actualCatalogue);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
index a2bcbcb9def38..ef6fa9330b0d8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
@@ -11,12 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Translation;
+use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Translation\MessageSelector;
-class TranslatorTest extends \PHPUnit_Framework_TestCase
+class TranslatorTest extends TestCase
{
protected $tmpDir;
@@ -41,6 +43,157 @@ protected function deleteTmpDir()
$fs->remove($dir);
}
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ */
+ public function testTransWithoutCachingOmittingLocale()
+ {
+ $translator = $this->getTranslator($this->getLoader(), array(), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setLocale('fr');
+ $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
+
+ $this->assertEquals('foo (FR)', $translator->trans('foo'));
+ $this->assertEquals('bar (EN)', $translator->trans('bar'));
+ $this->assertEquals('foobar (ES)', $translator->trans('foobar'));
+ $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
+ $this->assertEquals('no translation', $translator->trans('no translation'));
+ $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
+ $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
+ $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
+ $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ */
+ public function testTransWithCachingOmittingLocale()
+ {
+ // prime the cache
+ $translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setLocale('fr');
+ $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
+
+ $this->assertEquals('foo (FR)', $translator->trans('foo'));
+ $this->assertEquals('bar (EN)', $translator->trans('bar'));
+ $this->assertEquals('foobar (ES)', $translator->trans('foobar'));
+ $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
+ $this->assertEquals('no translation', $translator->trans('no translation'));
+ $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
+ $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
+ $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
+ $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
+
+ // do it another time as the cache is primed now
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
+ $loader->expects($this->never())->method('load');
+
+ $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setLocale('fr');
+ $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
+
+ $this->assertEquals('foo (FR)', $translator->trans('foo'));
+ $this->assertEquals('bar (EN)', $translator->trans('bar'));
+ $this->assertEquals('foobar (ES)', $translator->trans('foobar'));
+ $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
+ $this->assertEquals('no translation', $translator->trans('no translation'));
+ $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
+ $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
+ $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
+ $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ * @expectedException \InvalidArgumentException
+ */
+ public function testTransWithCachingWithInvalidLocaleOmittingLocale()
+ {
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
+ $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale', null);
+
+ $translator->trans('foo');
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ */
+ public function testLoadResourcesWithoutCachingOmittingLocale()
+ {
+ $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
+ $resourceFiles = array(
+ 'fr' => array(
+ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
+ ),
+ );
+
+ $translator = $this->getTranslator($loader, array('resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setLocale('fr');
+
+ $this->assertEquals('répertoire', $translator->trans('folder'));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ */
+ public function testGetDefaultLocaleOmittingLocale()
+ {
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
+ $container
+ ->expects($this->once())
+ ->method('getParameter')
+ ->with('kernel.default_locale')
+ ->will($this->returnValue('en'))
+ ;
+ $translator = new Translator($container, new MessageSelector());
+
+ $this->assertSame('en', $translator->getLocale());
+ }
+
+ /**
+ * @group legacy
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Missing third $defaultLocale argument.
+ */
+ public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
+ {
+ $container = $this->getMockBuilder(ContainerInterface::class)->getMock();
+ $translator = new Translator($container, new MessageSelector());
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
+ */
+ public function testWarmupOmittingLocale()
+ {
+ $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
+ $resourceFiles = array(
+ 'fr' => array(
+ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
+ ),
+ );
+
+ // prime the cache
+ $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setFallbackLocales(array('fr'));
+ $translator->warmup($this->tmpDir);
+
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
+ $loader
+ ->expects($this->never())
+ ->method('load');
+
+ $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
+ $translator->setLocale('fr');
+ $translator->setFallbackLocales(array('fr'));
+ $this->assertEquals('répertoire', $translator->trans('folder'));
+ }
+
public function testTransWithoutCaching()
{
$translator = $this->getTranslator($this->getLoader());
@@ -76,7 +229,7 @@ public function testTransWithCaching()
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
// do it another time as the cache is primed now
- $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
$loader->expects($this->never())->method('load');
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir));
@@ -96,10 +249,11 @@ public function testTransWithCaching()
/**
* @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Invalid "invalid locale" locale.
*/
public function testTransWithCachingWithInvalidLocale()
{
- $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale');
$translator->trans('foo');
@@ -122,19 +276,23 @@ public function testLoadResourcesWithoutCaching()
public function testGetDefaultLocale()
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
- $container
- ->expects($this->once())
- ->method('getParameter')
- ->with('kernel.default_locale')
- ->will($this->returnValue('en'))
- ;
-
- $translator = new Translator($container, new MessageSelector());
+ $container = $this->getMockBuilder(ContainerInterface::class)->getMock();
+ $translator = new Translator($container, new MessageSelector(), 'en');
$this->assertSame('en', $translator->getLocale());
}
+ /**
+ * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
+ * @expectedExceptionMessage The Translator does not support the following options: 'foo'
+ */
+ public function testInvalidOptions()
+ {
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
+
+ (new Translator($container, new MessageSelector(), 'en', array(), array('foo' => 'bar')));
+ }
+
protected function getCatalogue($locale, $messages, $resources = array())
{
$catalogue = new MessageCatalogue($locale);
@@ -150,7 +308,7 @@ protected function getCatalogue($locale, $messages, $resources = array())
protected function getLoader()
{
- $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
$loader
->expects($this->at(0))
->method('load')
@@ -208,7 +366,7 @@ protected function getLoader()
protected function getContainer($loader)
{
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->any())
->method('get')
@@ -218,9 +376,9 @@ protected function getContainer($loader)
return $container;
}
- public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator')
+ public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $defaultLocale = 'en')
{
- $translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat);
+ $translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat, $defaultLocale);
if ('loader' === $loaderFomat) {
$translator->addResource('loader', 'foo', 'fr');
@@ -249,7 +407,7 @@ public function testWarmup()
$translator->setFallbackLocales(array('fr'));
$translator->warmup($this->tmpDir);
- $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
$loader
->expects($this->never())
->method('load');
@@ -260,11 +418,21 @@ public function testWarmup()
$this->assertEquals('répertoire', $translator->trans('folder'));
}
- private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader')
+ private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader', $defaultLocale = 'en')
{
+ if (null === $defaultLocale) {
+ return new $translatorClass(
+ $this->getContainer($loader),
+ new MessageSelector(),
+ array($loaderFomat => array($loaderFomat)),
+ $options
+ );
+ }
+
return new $translatorClass(
$this->getContainer($loader),
new MessageSelector(),
+ $defaultLocale,
array($loaderFomat => array($loaderFomat)),
$options
);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php
index b61851bb0c86a..6cf9574ece96b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php
@@ -11,17 +11,18 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Validator;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Validator\Constraints\Blank as BlankConstraint;
-class ConstraintValidatorFactoryTest extends \PHPUnit_Framework_TestCase
+class ConstraintValidatorFactoryTest extends TestCase
{
public function testGetInstanceCreatesValidator()
{
$class = get_class($this->getMockForAbstractClass('Symfony\\Component\\Validator\\ConstraintValidator'));
- $constraint = $this->getMock('Symfony\\Component\\Validator\\Constraint');
+ $constraint = $this->getMockBuilder('Symfony\\Component\\Validator\\Constraint')->getMock();
$constraint
->expects($this->once())
->method('validatedBy')
@@ -46,14 +47,14 @@ public function testGetInstanceReturnsService()
$validator = $this->getMockForAbstractClass('Symfony\\Component\\Validator\\ConstraintValidator');
// mock ContainerBuilder b/c it implements TaggedContainerInterface
- $container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder', array('get'));
+ $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('get'))->getMock();
$container
->expects($this->once())
->method('get')
->with($service)
->will($this->returnValue($validator));
- $constraint = $this->getMock('Symfony\\Component\\Validator\\Constraint');
+ $constraint = $this->getMockBuilder('Symfony\\Component\\Validator\\Constraint')->getMock();
$constraint
->expects($this->once())
->method('validatedBy')
@@ -68,7 +69,7 @@ public function testGetInstanceReturnsService()
*/
public function testGetInstanceInvalidValidatorClass()
{
- $constraint = $this->getMock('Symfony\\Component\\Validator\\Constraint');
+ $constraint = $this->getMockBuilder('Symfony\\Component\\Validator\\Constraint')->getMock();
$constraint
->expects($this->once())
->method('validatedBy')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
index cf7f3c5769bf2..97c94fdd14bf9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php
@@ -24,6 +24,8 @@
class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
{
const MESSAGE_TOKEN = 300;
+ const METHOD_ARGUMENTS_TOKEN = 1000;
+ const DOMAIN_TOKEN = 1001;
/**
* Prefix for new found message.
@@ -38,6 +40,28 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
* @var array
*/
protected $sequences = array(
+ array(
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ),
+ array(
+ '->',
+ 'transChoice',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ),
array(
'->',
'trans',
@@ -105,11 +129,32 @@ private function seekToNextRelevantToken(\Iterator $tokenIterator)
}
}
+ private function skipMethodArgument(\Iterator $tokenIterator)
+ {
+ $openBraces = 0;
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+
+ if ('[' === $t[0] || '(' === $t[0]) {
+ ++$openBraces;
+ }
+
+ if (']' === $t[0] || ')' === $t[0]) {
+ --$openBraces;
+ }
+
+ if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) {
+ break;
+ }
+ }
+ }
+
/**
* Extracts the message from the iterator while the tokens
* match allowed message tokens.
*/
- private function getMessage(\Iterator $tokenIterator)
+ private function getValue(\Iterator $tokenIterator)
{
$message = '';
$docToken = '';
@@ -155,16 +200,26 @@ protected function parseTokens($tokens, MessageCatalogue $catalog)
for ($key = 0; $key < $tokenIterator->count(); ++$key) {
foreach ($this->sequences as $sequence) {
$message = '';
+ $domain = 'messages';
$tokenIterator->seek($key);
- foreach ($sequence as $item) {
+ foreach ($sequence as $sequenceKey => $item) {
$this->seekToNextRelevantToken($tokenIterator);
- if ($this->normalizeToken($tokenIterator->current()) == $item) {
+ if ($this->normalizeToken($tokenIterator->current()) === $item) {
$tokenIterator->next();
continue;
- } elseif (self::MESSAGE_TOKEN == $item) {
- $message = $this->getMessage($tokenIterator);
+ } elseif (self::MESSAGE_TOKEN === $item) {
+ $message = $this->getValue($tokenIterator);
+
+ if (count($sequence) === ($sequenceKey + 1)) {
+ break;
+ }
+ } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) {
+ $this->skipMethodArgument($tokenIterator);
+ } elseif (self::DOMAIN_TOKEN === $item) {
+ $domain = $this->getValue($tokenIterator);
+
break;
} else {
break;
@@ -172,7 +227,7 @@ protected function parseTokens($tokens, MessageCatalogue $catalog)
}
if ($message) {
- $catalog->set($message, $this->prefix.$message);
+ $catalog->set($message, $this->prefix.$message, $domain);
break;
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
index fedc425a11a07..6bcbaa8e97416 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
@@ -11,10 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\Translation;
+use Psr\Container\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\Translation\Translator as BaseTranslator;
use Symfony\Component\Translation\MessageSelector;
-use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
/**
@@ -54,8 +55,20 @@ class Translator extends BaseTranslator implements WarmableInterface
*
* @throws InvalidArgumentException
*/
- public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array())
+ public function __construct(ContainerInterface $container, MessageSelector $selector, $defaultLocale = null, array $loaderIds = array(), array $options = array())
{
+ // BC 3.x, to be removed in 4.0 along with the $defaultLocale default value
+ if (is_array($defaultLocale) || 3 > func_num_args()) {
+ if (!$container instanceof SymfonyContainerInterface) {
+ throw new \InvalidArgumentException('Missing third $defaultLocale argument.');
+ }
+
+ $options = $loaderIds;
+ $loaderIds = $defaultLocale;
+ $defaultLocale = $container->getParameter('kernel.default_locale');
+ @trigger_error(sprintf('Method %s() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.', __METHOD__), E_USER_DEPRECATED);
+ }
+
$this->container = $container;
$this->loaderIds = $loaderIds;
@@ -70,7 +83,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele
$this->loadResources();
}
- parent::__construct($container->getParameter('kernel.default_locale'), $selector, $this->options['cache_dir'], $this->options['debug']);
+ parent::__construct($defaultLocale, $selector, $this->options['cache_dir'], $this->options['debug']);
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
index 4e36678212baa..aba02e0944e22 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
@@ -11,7 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Validator;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\ConstraintValidatorInterface;
@@ -37,6 +37,8 @@
* }
*
* @author Kris Wallsmith
+ *
+ * @final since version 3.3
*/
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
@@ -70,11 +72,15 @@ public function getInstance(Constraint $constraint)
$name = $constraint->validatedBy();
if (!isset($this->validators[$name])) {
- if (!class_exists($name)) {
- throw new ValidatorException(sprintf('Constraint validator "%s" does not exist or it is not enabled. Check the "validatedBy" method in your constraint class "%s".', $name, get_class($constraint)));
- }
+ if ($this->container->has($name)) {
+ $this->validators[$name] = $this->container->get($name);
+ } else {
+ if (!class_exists($name)) {
+ throw new ValidatorException(sprintf('Constraint validator "%s" does not exist or it is not enabled. Check the "validatedBy" method in your constraint class "%s".', $name, get_class($constraint)));
+ }
- $this->validators[$name] = new $name();
+ $this->validators[$name] = new $name();
+ }
} elseif (is_string($this->validators[$name])) {
$this->validators[$name] = $this->container->get($this->validators[$name]);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index 278fadaf98d10..d613ecbc01f8b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -17,46 +17,61 @@
],
"require": {
"php": ">=5.5.9",
- "symfony/cache": "~3.2",
+ "symfony/cache": "~3.3",
"symfony/class-loader": "~3.2",
- "symfony/dependency-injection": "~3.2",
- "symfony/config": "~2.8|~3.0",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/http-foundation": "~3.1",
- "symfony/http-kernel": "~3.2",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/config": "~3.3",
+ "symfony/event-dispatcher": "~3.3",
+ "symfony/http-foundation": "~3.3",
+ "symfony/http-kernel": "~3.3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/filesystem": "~2.8|~3.0",
"symfony/finder": "~2.8|~3.0",
- "symfony/routing": "~3.0",
+ "symfony/routing": "~3.3",
+ "symfony/security-core": "~2.8|~3.0",
+ "symfony/security-csrf": "~2.8|~3.0",
"symfony/stopwatch": "~2.8|~3.0",
"doctrine/cache": "~1.0"
},
"require-dev": {
- "symfony/asset": "~2.8|~3.0",
+ "fig/link-util": "^1.0",
+ "symfony/asset": "~3.3",
"symfony/browser-kit": "~2.8|~3.0",
- "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2",
+ "symfony/console": "~3.3",
"symfony/css-selector": "~2.8|~3.0",
"symfony/dom-crawler": "~2.8|~3.0",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/security": "~2.8|~3.0",
- "symfony/form": "~2.8|~3.0",
+ "symfony/form": "~3.3",
"symfony/expression-language": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0",
"symfony/security-core": "~3.2",
"symfony/security-csrf": "~2.8|~3.0",
- "symfony/serializer": "~2.8|~3.0",
- "symfony/translation": "~2.8|~3.0",
+ "symfony/serializer": "~3.3",
+ "symfony/translation": "~3.2",
"symfony/templating": "~2.8|~3.0",
- "symfony/validator": "~3.2",
+ "symfony/validator": "~3.3",
+ "symfony/workflow": "~3.3",
"symfony/yaml": "~3.2",
- "symfony/property-info": "~2.8|~3.0",
+ "symfony/property-info": "~3.3",
+ "symfony/web-link": "~3.3",
"doctrine/annotations": "~1.0",
"phpdocumentor/reflection-docblock": "^3.0",
- "twig/twig": "~1.26|~2.0"
+ "twig/twig": "~1.26|~2.0",
+ "sensio/framework-extra-bundle": "^3.0.2"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<3.0",
- "phpdocumentor/type-resolver": "<0.2.0"
+ "phpdocumentor/type-resolver": "<0.2.0",
+ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
+ "symfony/asset": "<3.3",
+ "symfony/console": "<3.3",
+ "symfony/form": "<3.3",
+ "symfony/property-info": "<3.3",
+ "symfony/serializer": "<3.3",
+ "symfony/translation": "<3.2",
+ "symfony/validator": "<3.3",
+ "symfony/workflow": "<3.3"
},
"suggest": {
"ext-apcu": "For best performance of the system caches",
@@ -66,7 +81,8 @@
"symfony/validator": "For using validation",
"symfony/yaml": "For using the debug:config and lint:yaml commands",
"symfony/property-info": "For using the property_info service",
- "symfony/process": "For using the server:run, server:start, server:stop, and server:status commands"
+ "symfony/process": "For using the server:run, server:start, server:stop, and server:status commands",
+ "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering"
},
"autoload": {
"psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" },
@@ -77,7 +93,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist
index a105f7ece0a98..b447e1ac3e761 100644
--- a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist
+++ b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist
@@ -5,10 +5,13 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
+
diff --git a/src/Symfony/Bundle/FullStack.php b/src/Symfony/Bundle/FullStack.php
new file mode 100644
index 0000000000000..b884a47173e2e
--- /dev/null
+++ b/src/Symfony/Bundle/FullStack.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle;
+
+/**
+ * A marker to be able to check if symfony/symfony is installed instead of the individual components/bundles.
+ *
+ * @internal
+ */
+final class FullStack
+{
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
index d83d4a62d1e54..9691e5af03c16 100644
--- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
@@ -1,6 +1,16 @@
CHANGELOG
=========
+3.3.0
+-----
+
+ * Deprecated instantiating `UserPasswordEncoderCommand` without its constructor
+ arguments fully provided.
+ * Deprecated `UserPasswordEncoderCommand::getContainer()` and relying on the
+ `ContainerAwareInterface` interface for this command.
+ * Deprecated the `FirewallMap::$map` and `$container` properties.
+ * [BC BREAK] Keys of the `users` node for `in_memory` user provider are no longer normalized.
+
3.2.0
-----
diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
index 7151175d938e7..a588bdd331e96 100644
--- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
+++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
@@ -15,10 +15,14 @@
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
+use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
+use Symfony\Component\Security\Core\User\User;
/**
* Encode a user's password.
@@ -27,6 +31,31 @@
*/
class UserPasswordEncoderCommand extends ContainerAwareCommand
{
+ private $encoderFactory;
+ private $userClasses;
+
+ public function __construct(EncoderFactoryInterface $encoderFactory = null, array $userClasses = array())
+ {
+ if (null === $encoderFactory) {
+ @trigger_error(sprintf('Passing null as the first argument of "%s" is deprecated since version 3.3 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED);
+ }
+
+ $this->encoderFactory = $encoderFactory;
+ $this->userClasses = $userClasses;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getContainer()
+ {
+ @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareInterface::class), E_USER_DEPRECATED);
+
+ return parent::getContainer();
+ }
+
/**
* {@inheritdoc}
*/
@@ -36,7 +65,7 @@ protected function configure()
->setName('security:encode-password')
->setDescription('Encodes a password.')
->addArgument('password', InputArgument::OPTIONAL, 'The plain password to encode.')
- ->addArgument('user-class', InputArgument::OPTIONAL, 'The User entity class path associated with the encoder used to encode the password.', 'Symfony\Component\Security\Core\User\User')
+ ->addArgument('user-class', InputArgument::OPTIONAL, 'The User entity class path associated with the encoder used to encode the password.')
->addOption('empty-salt', null, InputOption::VALUE_NONE, 'Do not generate a salt or let the encoder generate one.')
->setHelp(<<
-If you execute the command non-interactively, the default Symfony User class
-is used and a random salt is generated to encode the password:
+If you execute the command non-interactively, the first available configured
+user class under the security.encoders key is used and a random salt is
+generated to encode the password:
php %command.full_name% --no-interaction [password]
@@ -85,14 +115,16 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
+ $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io;
- $input->isInteractive() ? $io->title('Symfony Password Encoder Utility') : $io->newLine();
+ $input->isInteractive() ? $errorIo->title('Symfony Password Encoder Utility') : $errorIo->newLine();
$password = $input->getArgument('password');
- $userClass = $input->getArgument('user-class');
+ $userClass = $this->getUserClass($input, $io);
$emptySalt = $input->getOption('empty-salt');
- $encoder = $this->getContainer()->get('security.encoder_factory')->getEncoder($userClass);
+ $encoderFactory = $this->encoderFactory ?: parent::getContainer()->get('security.encoder_factory');
+ $encoder = $encoderFactory->getEncoder($userClass);
$bcryptWithoutEmptySalt = !$emptySalt && $encoder instanceof BCryptPasswordEncoder;
if ($bcryptWithoutEmptySalt) {
@@ -101,12 +133,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (!$password) {
if (!$input->isInteractive()) {
- $io->error('The password must not be empty.');
+ $errorIo->error('The password must not be empty.');
return 1;
}
$passwordQuestion = $this->createPasswordQuestion();
- $password = $io->askQuestion($passwordQuestion);
+ $password = $errorIo->askQuestion($passwordQuestion);
}
$salt = null;
@@ -114,9 +146,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($input->isInteractive() && !$emptySalt) {
$emptySalt = true;
- $io->note('The command will take care of generating a salt for you. Be aware that some encoders advise to let them generate their own salt. If you\'re using one of those encoders, please answer \'no\' to the question below. '.PHP_EOL.'Provide the \'empty-salt\' option in order to let the encoder handle the generation itself.');
+ $errorIo->note('The command will take care of generating a salt for you. Be aware that some encoders advise to let them generate their own salt. If you\'re using one of those encoders, please answer \'no\' to the question below. '.PHP_EOL.'Provide the \'empty-salt\' option in order to let the encoder handle the generation itself.');
- if ($io->confirm('Confirm salt generation ?')) {
+ if ($errorIo->confirm('Confirm salt generation ?')) {
$salt = $this->generateSalt();
$emptySalt = false;
}
@@ -136,12 +168,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
$io->table(array('Key', 'Value'), $rows);
if (!$emptySalt) {
- $io->note(sprintf('Make sure that your salt storage field fits the salt length: %s chars', strlen($salt)));
+ $errorIo->note(sprintf('Make sure that your salt storage field fits the salt length: %s chars', strlen($salt)));
} elseif ($bcryptWithoutEmptySalt) {
- $io->note('Bcrypt encoder used: the encoder generated its own built-in salt.');
+ $errorIo->note('Bcrypt encoder used: the encoder generated its own built-in salt.');
}
- $io->success('Password encoding succeeded');
+ $errorIo->success('Password encoding succeeded');
}
/**
@@ -166,4 +198,30 @@ private function generateSalt()
{
return base64_encode(random_bytes(30));
}
+
+ private function getUserClass(InputInterface $input, SymfonyStyle $io)
+ {
+ if (null !== $userClass = $input->getArgument('user-class')) {
+ return $userClass;
+ }
+
+ if (empty($this->userClasses)) {
+ if (null === $this->encoderFactory) {
+ // BC to be removed and simply keep the exception whenever there is no configured user classes in 4.0
+ return User::class;
+ }
+
+ throw new \RuntimeException('There are no configured encoders for the "security" extension.');
+ }
+
+ if (!$input->isInteractive() || 1 === count($this->userClasses)) {
+ return reset($this->userClasses);
+ }
+
+ $userClasses = $this->userClasses;
+ natcasesort($userClasses);
+ $userClasses = array_values($userClasses);
+
+ return $io->choice('For which user class would you like to encode a password?', $userClasses, reset($userClasses));
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
index 544e1de1921af..6831e94d047af 100644
--- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
+++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
@@ -16,10 +16,12 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
-use Symfony\Component\Security\Core\Authorization\DebugAccessDecisionManager;
+use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
+use Symfony\Component\VarDumper\Caster\ClassStub;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\Security\Http\FirewallMapInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
@@ -29,13 +31,14 @@
*
* @author Fabien Potencier
*/
-class SecurityDataCollector extends DataCollector
+class SecurityDataCollector extends DataCollector implements LateDataCollectorInterface
{
private $tokenStorage;
private $roleHierarchy;
private $logoutUrlGenerator;
private $accessDecisionManager;
private $firewallMap;
+ private $hasVarDumper;
/**
* Constructor.
@@ -53,6 +56,7 @@ public function __construct(TokenStorageInterface $tokenStorage = null, RoleHier
$this->logoutUrlGenerator = $logoutUrlGenerator;
$this->accessDecisionManager = $accessDecisionManager;
$this->firewallMap = $firewallMap;
+ $this->hasVarDumper = class_exists(ClassStub::class);
}
/**
@@ -109,28 +113,23 @@ public function collect(Request $request, Response $response, \Exception $except
$this->data = array(
'enabled' => true,
'authenticated' => $token->isAuthenticated(),
- 'token' => $this->cloneVar($token),
- 'token_class' => get_class($token),
+ 'token' => $token,
+ 'token_class' => $this->hasVarDumper ? new ClassStub(get_class($token)) : get_class($token),
'logout_url' => $logoutUrl,
'user' => $token->getUsername(),
- 'roles' => $this->cloneVar(array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles)),
- 'inherited_roles' => $this->cloneVar(array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles)),
+ '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,
);
}
// collect voters and access decision manager information
- if ($this->accessDecisionManager instanceof DebugAccessDecisionManager) {
- $this->data['access_decision_log'] = array_map(function ($decision) {
- $decision['object'] = $this->cloneVar($decision['object']);
-
- return $decision;
- }, $this->accessDecisionManager->getDecisionLog());
-
+ if ($this->accessDecisionManager instanceof TraceableAccessDecisionManager) {
+ $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog();
$this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy();
foreach ($this->accessDecisionManager->getVoters() as $voter) {
- $this->data['voters'][] = get_class($voter);
+ $this->data['voters'][] = $this->hasVarDumper ? new ClassStub(get_class($voter)) : get_class($voter);
}
} else {
$this->data['access_decision_log'] = array();
@@ -155,12 +154,17 @@ public function collect(Request $request, Response $response, \Exception $except
'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(),
'access_denied_url' => $firewallConfig->getAccessDeniedUrl(),
'user_checker' => $firewallConfig->getUserChecker(),
- 'listeners' => $this->cloneVar($firewallConfig->getListeners()),
+ 'listeners' => $firewallConfig->getListeners(),
);
}
}
}
+ public function lateCollect()
+ {
+ $this->data = $this->cloneVar($this->data);
+ }
+
/**
* Checks if security is enabled.
*
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
index e603cb9a81466..e907b7d56792f 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
@@ -11,9 +11,10 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\Exception\LogicException;
/**
@@ -23,6 +24,8 @@
*/
class AddSecurityVotersPass implements CompilerPassInterface
{
+ use PriorityTaggedServiceTrait;
+
/**
* {@inheritdoc}
*/
@@ -32,20 +35,12 @@ public function process(ContainerBuilder $container)
return;
}
- $voters = new \SplPriorityQueue();
- foreach ($container->findTaggedServiceIds('security.voter') as $id => $attributes) {
- $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
- $voters->insert(new Reference($id), $priority);
- }
-
- $voters = iterator_to_array($voters);
- ksort($voters);
-
+ $voters = $this->findAndSortTaggedServices('security.voter', $container);
if (!$voters) {
throw new LogicException('No security voters found. You need to tag at least one with "security.voter"');
}
- $adm = $container->getDefinition($container->hasDefinition('debug.security.access.decision_manager') ? 'debug.security.access.decision_manager' : 'security.access.decision_manager');
- $adm->addMethodCall('setVoters', array(array_values($voters)));
+ $adm = $container->getDefinition('security.access.decision_manager');
+ $adm->replaceArgument(0, new IteratorArgument($voters));
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
index b0aadc2f19e43..c2bcb7d0e3ef2 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
@@ -369,11 +369,11 @@ private function addProvidersSection(ArrayNodeDefinition $rootNode)
$providerNodeBuilder
->validate()
- ->ifTrue(function ($v) {return count($v) > 1;})
+ ->ifTrue(function ($v) { return count($v) > 1; })
->thenInvalid('You cannot set multiple provider types for the same provider')
->end()
->validate()
- ->ifTrue(function ($v) {return count($v) === 0;})
+ ->ifTrue(function ($v) { return count($v) === 0; })
->thenInvalid('You must set a provider definition for the provider.')
->end()
;
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php
index cdb0a96fe4175..356e9f8327d2e 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -156,7 +156,7 @@ protected function isRememberMeAware($config)
protected function createListener($container, $id, $config, $userProvider)
{
$listenerId = $this->getListenerId();
- $listener = new DefinitionDecorator($listenerId);
+ $listener = new ChildDefinition($listenerId);
$listener->replaceArgument(4, $id);
$listener->replaceArgument(5, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)));
$listener->replaceArgument(6, new Reference($this->createAuthenticationFailureHandler($container, $id, $config)));
@@ -174,12 +174,12 @@ protected function createAuthenticationSuccessHandler($container, $id, $config)
$options = array_intersect_key($config, $this->defaultSuccessHandlerOptions);
if (isset($config['success_handler'])) {
- $successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.custom_success_handler'));
+ $successHandler = $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.custom_success_handler'));
$successHandler->replaceArgument(0, new Reference($config['success_handler']));
$successHandler->replaceArgument(1, $options);
$successHandler->replaceArgument(2, $id);
} else {
- $successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.success_handler'));
+ $successHandler = $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.success_handler'));
$successHandler->addMethodCall('setOptions', array($options));
$successHandler->addMethodCall('setProviderKey', array($id));
}
@@ -193,11 +193,11 @@ protected function createAuthenticationFailureHandler($container, $id, $config)
$options = array_intersect_key($config, $this->defaultFailureHandlerOptions);
if (isset($config['failure_handler'])) {
- $failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.custom_failure_handler'));
+ $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.custom_failure_handler'));
$failureHandler->replaceArgument(0, new Reference($config['failure_handler']));
$failureHandler->replaceArgument(1, $options);
} else {
- $failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.failure_handler'));
+ $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.failure_handler'));
$failureHandler->addMethodCall('setOptions', array($options));
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php
index 021c050b79247..24f0b98ae6fbb 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -63,7 +63,7 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config,
{
$provider = 'security.authentication.provider.dao.'.$id;
$container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.dao'))
->replaceArgument(0, new Reference($userProviderId))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->replaceArgument(2, $id)
@@ -88,7 +88,7 @@ protected function createEntryPoint($container, $id, $config, $defaultEntryPoint
{
$entryPointId = 'security.authentication.form_entry_point.'.$id;
$container
- ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
+ ->setDefinition($entryPointId, new ChildDefinition('security.authentication.form_entry_point'))
->addArgument(new Reference('security.http_utils'))
->addArgument($config['login_path'])
->addArgument($config['use_forward'])
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php
index 2932f2c1025e7..8bd389dc95b4c 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -27,8 +27,8 @@ class FormLoginLdapFactory extends FormLoginFactory
protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)
{
$provider = 'security.authentication.provider.ldap_bind.'.$id;
- $container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind'))
+ $definition = $container
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.ldap_bind'))
->replaceArgument(0, new Reference($userProviderId))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->replaceArgument(2, $id)
@@ -36,6 +36,10 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config,
->replaceArgument(4, $config['dn_string'])
;
+ if (!empty($config['query_string'])) {
+ $definition->addMethodCall('setQueryString', array($config['query_string']));
+ }
+
return $provider;
}
@@ -47,6 +51,7 @@ public function addConfiguration(NodeDefinition $node)
->children()
->scalarNode('service')->defaultValue('ldap')->end()
->scalarNode('dn_string')->defaultValue('{username}')->end()
+ ->scalarNode('query_string')->end()
->end()
;
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php
index 67bdeceb346c7..d02395b916a0c 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php
@@ -12,8 +12,9 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;
/**
@@ -62,11 +63,13 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
$authenticatorReferences[] = new Reference($authenticatorId);
}
+ $authenticators = new IteratorArgument($authenticatorReferences);
+
// configure the GuardAuthenticationFactory to have the dynamic constructor arguments
$providerId = 'security.authentication.provider.guard.'.$id;
$container
- ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.guard'))
- ->replaceArgument(0, $authenticatorReferences)
+ ->setDefinition($providerId, new ChildDefinition('security.authentication.provider.guard'))
+ ->replaceArgument(0, $authenticators)
->replaceArgument(1, new Reference($userProvider))
->replaceArgument(2, $id)
->replaceArgument(3, new Reference('security.user_checker.'.$id))
@@ -74,9 +77,9 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// listener
$listenerId = 'security.authentication.listener.guard.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.guard'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.guard'));
$listener->replaceArgument(2, $id);
- $listener->replaceArgument(3, $authenticatorReferences);
+ $listener->replaceArgument(3, $authenticators);
// determine the entryPointId to use
$entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config);
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php
index 162ea05157984..3bfb50718bfa4 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -27,7 +27,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$provider = 'security.authentication.provider.dao.'.$id;
$container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.dao'))
->replaceArgument(0, new Reference($userProvider))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->replaceArgument(2, $id)
@@ -38,7 +38,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// listener
$listenerId = 'security.authentication.listener.basic.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.basic'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.basic'));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, new Reference($entryPointId));
@@ -73,7 +73,7 @@ protected function createEntryPoint($container, $id, $config, $defaultEntryPoint
$entryPointId = 'security.authentication.basic_entry_point.'.$id;
$container
- ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.basic_entry_point'))
+ ->setDefinition($entryPointId, new ChildDefinition('security.authentication.basic_entry_point'))
->addArgument($config['realm'])
;
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php
index 2b7e6201dfa44..ce3cdda96eafd 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -28,8 +28,8 @@ class HttpBasicLdapFactory extends HttpBasicFactory
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{
$provider = 'security.authentication.provider.ldap_bind.'.$id;
- $container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind'))
+ $definition = $container
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.ldap_bind'))
->replaceArgument(0, new Reference($userProvider))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->replaceArgument(2, $id)
@@ -40,9 +40,13 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// entry point
$entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint);
+ if (!empty($config['query_string'])) {
+ $definition->addMethodCall('setQueryString', array($config['query_string']));
+ }
+
// listener
$listenerId = 'security.authentication.listener.basic.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.basic'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.basic'));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, new Reference($entryPointId));
@@ -57,6 +61,7 @@ public function addConfiguration(NodeDefinition $node)
->children()
->scalarNode('service')->defaultValue('ldap')->end()
->scalarNode('dn_string')->defaultValue('{username}')->end()
+ ->scalarNode('query_string')->end()
->end()
;
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php
index a360504572656..bedc87864c235 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -27,7 +27,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$provider = 'security.authentication.provider.dao.'.$id;
$container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.dao'))
->replaceArgument(0, new Reference($userProvider))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->replaceArgument(2, $id)
@@ -38,7 +38,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// listener
$listenerId = 'security.authentication.listener.digest.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.digest'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.digest'));
$listener->replaceArgument(1, new Reference($userProvider));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, new Reference($entryPointId));
@@ -75,7 +75,7 @@ protected function createEntryPoint($container, $id, $config, $defaultEntryPoint
$entryPointId = 'security.authentication.digest_entry_point.'.$id;
$container
- ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.digest_entry_point'))
+ ->setDefinition($entryPointId, new ChildDefinition('security.authentication.digest_entry_point'))
->addArgument($config['realm'])
->addArgument($config['secret'])
;
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php
new file mode 100644
index 0000000000000..c69cab8949af6
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php
@@ -0,0 +1,101 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * JsonLoginFactory creates services for JSON login authentication.
+ *
+ * @author Kévin Dunglas
+ *
+ * @experimental in version 3.3
+ */
+class JsonLoginFactory extends AbstractFactory
+{
+ public function __construct()
+ {
+ $this->addOption('username_path', 'username');
+ $this->addOption('password_path', 'password');
+ $this->defaultFailureHandlerOptions = array();
+ $this->defaultSuccessHandlerOptions = array();
+ $this->options['require_previous_session'] = false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPosition()
+ {
+ return 'form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getKey()
+ {
+ return 'json-login';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)
+ {
+ $provider = 'security.authentication.provider.dao.'.$id;
+ $container
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.dao'))
+ ->replaceArgument(0, new Reference($userProviderId))
+ ->replaceArgument(1, new Reference('security.user_checker.'.$id))
+ ->replaceArgument(2, $id)
+ ;
+
+ return $provider;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getListenerId()
+ {
+ return 'security.authentication.listener.json';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function isRememberMeAware($config)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function createListener($container, $id, $config, $userProvider)
+ {
+ $listenerId = $this->getListenerId();
+ $listener = new ChildDefinition($listenerId);
+ $listener->replaceArgument(3, $id);
+ $listener->replaceArgument(4, isset($config['success_handler']) ? new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)) : null);
+ $listener->replaceArgument(5, isset($config['failure_handler']) ? new Reference($this->createAuthenticationFailureHandler($container, $id, $config)) : null);
+ $listener->replaceArgument(6, array_intersect_key($config, $this->options));
+
+ $listenerId .= '.'.$id;
+ $container->setDefinition($listenerId, $listener);
+
+ return $listenerId;
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
index fc008a9fbd82c..a0f6889388d94 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -34,7 +34,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// authentication provider
$authProviderId = 'security.authentication.provider.rememberme.'.$id;
$container
- ->setDefinition($authProviderId, new DefinitionDecorator('security.authentication.provider.rememberme'))
+ ->setDefinition($authProviderId, new ChildDefinition('security.authentication.provider.rememberme'))
->replaceArgument(0, new Reference('security.user_checker.'.$id))
->addArgument($config['secret'])
->addArgument($id)
@@ -56,7 +56,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
;
}
- $rememberMeServices = $container->setDefinition($rememberMeServicesId, new DefinitionDecorator($templateId));
+ $rememberMeServices = $container->setDefinition($rememberMeServicesId, new ChildDefinition($templateId));
$rememberMeServices->replaceArgument(1, $config['secret']);
$rememberMeServices->replaceArgument(2, $id);
@@ -97,11 +97,12 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
if (count($userProviders) === 0) {
throw new \RuntimeException('You must configure at least one remember-me aware listener (such as form-login) for each firewall that has remember-me enabled.');
}
- $rememberMeServices->replaceArgument(0, $userProviders);
+
+ $rememberMeServices->replaceArgument(0, array_unique($userProviders));
// remember-me listener
$listenerId = 'security.authentication.listener.rememberme.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.rememberme'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.rememberme'));
$listener->replaceArgument(1, new Reference($rememberMeServicesId));
$listener->replaceArgument(5, $config['catch_exceptions']);
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php
index cf2e2ed71b16c..5e0c9d716b8f5 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -28,14 +28,14 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$providerId = 'security.authentication.provider.pre_authenticated.'.$id;
$container
- ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.pre_authenticated'))
+ ->setDefinition($providerId, new ChildDefinition('security.authentication.provider.pre_authenticated'))
->replaceArgument(0, new Reference($userProvider))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->addArgument($id)
;
$listenerId = 'security.authentication.listener.remote_user.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.remote_user'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.remote_user'));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, $config['user']);
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php
index 9da6601ff547b..1f45ab1a44985 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -51,7 +51,7 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config,
{
$provider = 'security.authentication.provider.simple_form.'.$id;
$container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.simple'))
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.simple'))
->replaceArgument(0, new Reference($config['authenticator']))
->replaceArgument(1, new Reference($userProviderId))
->replaceArgument(2, $id)
@@ -65,7 +65,7 @@ protected function createListener($container, $id, $config, $userProvider)
$listenerId = parent::createListener($container, $id, $config, $userProvider);
$simpleAuthHandlerId = 'security.authentication.simple_success_failure_handler.'.$id;
- $simpleAuthHandler = $container->setDefinition($simpleAuthHandlerId, new DefinitionDecorator('security.authentication.simple_success_failure_handler'));
+ $simpleAuthHandler = $container->setDefinition($simpleAuthHandlerId, new ChildDefinition('security.authentication.simple_success_failure_handler'));
$simpleAuthHandler->replaceArgument(0, new Reference($config['authenticator']));
$simpleAuthHandler->replaceArgument(1, new Reference($this->getSuccessHandlerId($id)));
$simpleAuthHandler->replaceArgument(2, new Reference($this->getFailureHandlerId($id)));
@@ -77,17 +77,4 @@ protected function createListener($container, $id, $config, $userProvider)
return $listenerId;
}
-
- protected function createEntryPoint($container, $id, $config, $defaultEntryPoint)
- {
- $entryPointId = 'security.authentication.form_entry_point.'.$id;
- $container
- ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
- ->addArgument(new Reference('security.http_utils'))
- ->addArgument($config['login_path'])
- ->addArgument($config['use_forward'])
- ;
-
- return $entryPointId;
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php
index 27d8c5f050ec5..b1304a55b3f87 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -45,7 +45,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$provider = 'security.authentication.provider.simple_preauth.'.$id;
$container
- ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.simple'))
+ ->setDefinition($provider, new ChildDefinition('security.authentication.provider.simple'))
->replaceArgument(0, new Reference($config['authenticator']))
->replaceArgument(1, new Reference($userProvider))
->replaceArgument(2, $id)
@@ -53,7 +53,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// listener
$listenerId = 'security.authentication.listener.simple_preauth.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.simple_preauth'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.simple_preauth'));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, new Reference($config['authenticator']));
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php
index 0467ef2ba2c75..39a1016b34bb1 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -27,7 +27,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$providerId = 'security.authentication.provider.pre_authenticated.'.$id;
$container
- ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.pre_authenticated'))
+ ->setDefinition($providerId, new ChildDefinition('security.authentication.provider.pre_authenticated'))
->replaceArgument(0, new Reference($userProvider))
->replaceArgument(1, new Reference('security.user_checker.'.$id))
->addArgument($id)
@@ -35,7 +35,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
// listener
$listenerId = 'security.authentication.listener.x509.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.x509'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.x509'));
$listener->replaceArgument(2, $id);
$listener->replaceArgument(3, $config['user']);
$listener->replaceArgument(4, $config['credentials']);
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php
index b184385f221fa..f226b47cf5cc5 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -26,13 +26,13 @@ class InMemoryFactory implements UserProviderFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config)
{
- $definition = $container->setDefinition($id, new DefinitionDecorator('security.user.provider.in_memory'));
+ $definition = $container->setDefinition($id, new ChildDefinition('security.user.provider.in_memory'));
foreach ($config['users'] as $username => $user) {
$userId = $id.'_'.$username;
$container
- ->setDefinition($userId, new DefinitionDecorator('security.user.provider.in_memory.user'))
+ ->setDefinition($userId, new ChildDefinition('security.user.provider.in_memory.user'))
->setArguments(array($username, (string) $user['password'], $user['roles']))
;
@@ -52,6 +52,7 @@ public function addConfiguration(NodeDefinition $node)
->children()
->arrayNode('users')
->useAttributeAsKey('name')
+ ->normalizeKeys(false)
->prototype('array')
->children()
->scalarNode('password')->defaultValue(uniqid('', true))->end()
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
index ecaf35364db91..f213a32f8b7dc 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -27,7 +27,7 @@ class LdapFactory implements UserProviderFactoryInterface
public function create(ContainerBuilder $container, $id, $config)
{
$container
- ->setDefinition($id, new DefinitionDecorator('security.user.provider.ldap'))
+ ->setDefinition($id, new ChildDefinition('security.user.provider.ldap'))
->replaceArgument(0, new Reference($config['service']))
->replaceArgument(1, $config['base_dn'])
->replaceArgument(2, $config['search_dn'])
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index faa28fc1757aa..a54244d67c663 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -14,14 +14,18 @@
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
* SecurityExtension.
@@ -94,6 +98,11 @@ public function load(array $configs, ContainerBuilder $container)
if ($config['encoders']) {
$this->createEncoders($config['encoders'], $container);
+
+ if (class_exists(Application::class)) {
+ $loader->load('console.xml');
+ $container->getDefinition('security.console.user_password_encoder_command')->replaceArgument(1, array_keys($config['encoders']));
+ }
}
// load ACL
@@ -101,20 +110,24 @@ public function load(array $configs, ContainerBuilder $container)
$this->aclLoad($config['acl'], $container);
}
- // add some required classes for compilation
- $this->addClassesToCompile(array(
- 'Symfony\Component\Security\Http\Firewall',
- 'Symfony\Component\Security\Core\User\UserProviderInterface',
- 'Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager',
- 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage',
- 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager',
- 'Symfony\Component\Security\Core\Authorization\AuthorizationChecker',
- 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface',
- 'Symfony\Bundle\SecurityBundle\Security\FirewallConfig',
- 'Symfony\Bundle\SecurityBundle\Security\FirewallMap',
- 'Symfony\Bundle\SecurityBundle\Security\FirewallContext',
- 'Symfony\Component\HttpFoundation\RequestMatcher',
- ));
+ $container->registerForAutoconfiguration(VoterInterface::class)
+ ->addTag('security.voter');
+
+ if (PHP_VERSION_ID < 70000) {
+ // add some required classes for compilation
+ $this->addClassesToCompile(array(
+ 'Symfony\Component\Security\Http\Firewall',
+ 'Symfony\Component\Security\Core\User\UserProviderInterface',
+ 'Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager',
+ 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage',
+ 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager',
+ 'Symfony\Component\Security\Core\Authorization\AuthorizationChecker',
+ 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface',
+ 'Symfony\Bundle\SecurityBundle\Security\FirewallConfig',
+ 'Symfony\Bundle\SecurityBundle\Security\FirewallContext',
+ 'Symfony\Component\HttpFoundation\RequestMatcher',
+ ));
+ }
}
private function aclLoad($config, ContainerBuilder $container)
@@ -191,9 +204,11 @@ private function createAuthorization($config, ContainerBuilder $container)
return;
}
- $this->addClassesToCompile(array(
- 'Symfony\\Component\\Security\\Http\\AccessMap',
- ));
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Symfony\\Component\\Security\\Http\\AccessMap',
+ ));
+ }
foreach ($config['access_control'] as $access) {
$matcher = $this->createRequestMatcher(
@@ -233,25 +248,33 @@ private function createFirewalls($config, ContainerBuilder $container)
$arguments[1] = $userProviders;
$definition->setArguments($arguments);
+ $customUserChecker = false;
+
// load firewall map
$mapDef = $container->getDefinition('security.firewall.map');
- $map = $authenticationProviders = array();
+ $map = $authenticationProviders = $contextRefs = array();
foreach ($firewalls as $name => $firewall) {
+ if (isset($firewall['user_checker']) && 'security.user_checker' !== $firewall['user_checker']) {
+ $customUserChecker = true;
+ }
+
$configId = 'security.firewall.map.config.'.$name;
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
$contextId = 'security.firewall.map.context.'.$name;
- $context = $container->setDefinition($contextId, new DefinitionDecorator('security.firewall.context'));
+ $context = $container->setDefinition($contextId, new ChildDefinition('security.firewall.context'));
$context
->replaceArgument(0, $listeners)
->replaceArgument(1, $exceptionListener)
->replaceArgument(2, new Reference($configId))
;
+ $contextRefs[$contextId] = new Reference($contextId);
$map[$contextId] = $matcher;
}
- $mapDef->replaceArgument(1, $map);
+ $mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
+ $mapDef->replaceArgument(1, new IteratorArgument($map));
// add authentication providers to authentication manager
$authenticationProviders = array_map(function ($id) {
@@ -259,13 +282,18 @@ private function createFirewalls($config, ContainerBuilder $container)
}, array_values(array_unique($authenticationProviders)));
$container
->getDefinition('security.authentication.manager')
- ->replaceArgument(0, $authenticationProviders)
+ ->replaceArgument(0, new IteratorArgument($authenticationProviders))
;
+
+ // register an autowire alias for the UserCheckerInterface if no custom user checker service is configured
+ if (!$customUserChecker) {
+ $container->setAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', new Alias('security.user_checker', false));
+ }
}
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds, $configId)
{
- $config = $container->setDefinition($configId, new DefinitionDecorator('security.firewall.config'));
+ $config = $container->setDefinition($configId, new ChildDefinition('security.firewall.config'));
$config->replaceArgument(0, $id);
$config->replaceArgument(1, $firewall['user_checker']);
@@ -323,7 +351,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
if (isset($firewall['logout'])) {
$listenerKeys[] = 'logout';
$listenerId = 'security.logout_listener.'.$id;
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.logout_listener'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.logout_listener'));
$listener->replaceArgument(3, array(
'csrf_parameter' => $firewall['logout']['csrf_parameter'],
'csrf_token_id' => $firewall['logout']['csrf_token_id'],
@@ -336,7 +364,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
$logoutSuccessHandlerId = $firewall['logout']['success_handler'];
} else {
$logoutSuccessHandlerId = 'security.logout.success_handler.'.$id;
- $logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new DefinitionDecorator('security.logout.success_handler'));
+ $logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new ChildDefinition('security.logout.success_handler'));
$logoutSuccessHandler->replaceArgument(1, $firewall['logout']['target']);
}
$listener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
@@ -354,7 +382,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
// add cookie logout handler
if (count($firewall['logout']['delete_cookies']) > 0) {
$cookieHandlerId = 'security.logout.handler.cookie_clearing.'.$id;
- $cookieHandler = $container->setDefinition($cookieHandlerId, new DefinitionDecorator('security.logout.handler.cookie_clearing'));
+ $cookieHandler = $container->setDefinition($cookieHandlerId, new ChildDefinition('security.logout.handler.cookie_clearing'));
$cookieHandler->addArgument($firewall['logout']['delete_cookies']);
$listener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
@@ -374,6 +402,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
$firewall['logout']['csrf_token_id'],
$firewall['logout']['csrf_parameter'],
isset($firewall['logout']['csrf_token_generator']) ? new Reference($firewall['logout']['csrf_token_generator']) : null,
+ false === $firewall['stateless'] && isset($firewall['context']) ? $firewall['context'] : null,
))
;
}
@@ -403,7 +432,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
$config->replaceArgument(8, isset($firewall['access_denied_handler']) ? $firewall['access_denied_handler'] : null);
$config->replaceArgument(9, isset($firewall['access_denied_url']) ? $firewall['access_denied_url'] : null);
- $container->setAlias(new Alias('security.user_checker.'.$id, false), $firewall['user_checker']);
+ $container->setAlias('security.user_checker.'.$id, new Alias($firewall['user_checker'], false));
foreach ($this->factories as $position) {
foreach ($position as $factory) {
@@ -430,7 +459,7 @@ private function createContextListener($container, $contextKey)
}
$listenerId = 'security.context_listener.'.count($this->contextListeners);
- $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.context_listener'));
+ $listener = $container->setDefinition($listenerId, new ChildDefinition('security.context_listener'));
$listener->replaceArgument(2, $contextKey);
return $this->contextListeners[$contextKey] = $listenerId;
@@ -461,7 +490,7 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut
if (isset($firewall['anonymous'])) {
$listenerId = 'security.authentication.listener.anonymous.'.$id;
$container
- ->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.anonymous'))
+ ->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.anonymous'))
->replaceArgument(1, $firewall['anonymous']['secret'])
;
@@ -469,7 +498,7 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut
$providerId = 'security.authentication.provider.anonymous.'.$id;
$container
- ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.anonymous'))
+ ->setDefinition($providerId, new ChildDefinition('security.authentication.provider.anonymous'))
->replaceArgument(0, $firewall['anonymous']['secret'])
;
@@ -554,7 +583,7 @@ private function createUserProviders($config, ContainerBuilder $container)
// Parses a tag and returns the id for the related user provider service
private function createUserDaoProvider($name, $provider, ContainerBuilder $container)
{
- $name = $this->getUserProviderId(strtolower($name));
+ $name = $this->getUserProviderId($name);
// Doctrine Entity and In-memory DAO provider are managed by factories
foreach ($this->userProviderFactories as $factory) {
@@ -578,11 +607,11 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta
if (isset($provider['chain'])) {
$providers = array();
foreach ($provider['chain']['providers'] as $providerName) {
- $providers[] = new Reference($this->getUserProviderId(strtolower($providerName)));
+ $providers[] = new Reference($this->getUserProviderId($providerName));
}
$container
- ->setDefinition($name, new DefinitionDecorator('security.user.provider.chain'))
+ ->setDefinition($name, new ChildDefinition('security.user.provider.chain'))
->addArgument($providers);
return $name;
@@ -593,13 +622,13 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta
private function getUserProviderId($name)
{
- return 'security.user.provider.concrete.'.$name;
+ return 'security.user.provider.concrete.'.strtolower($name);
}
private function createExceptionListener($container, $config, $id, $defaultEntryPoint, $stateless)
{
$exceptionListenerId = 'security.exception_listener.'.$id;
- $listener = $container->setDefinition($exceptionListenerId, new DefinitionDecorator('security.exception_listener'));
+ $listener = $container->setDefinition($exceptionListenerId, new ChildDefinition('security.exception_listener'));
$listener->replaceArgument(3, $id);
$listener->replaceArgument(4, null === $defaultEntryPoint ? null : new Reference($defaultEntryPoint));
$listener->replaceArgument(8, $stateless);
@@ -619,7 +648,7 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv
$userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider;
$switchUserListenerId = 'security.authentication.switchuser_listener.'.$id;
- $listener = $container->setDefinition($switchUserListenerId, new DefinitionDecorator('security.authentication.switchuser_listener'));
+ $listener = $container->setDefinition($switchUserListenerId, new ChildDefinition('security.authentication.switchuser_listener'));
$listener->replaceArgument(1, new Reference($userProvider));
$listener->replaceArgument(2, new Reference('security.user_checker.'.$id));
$listener->replaceArgument(3, $id);
diff --git a/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallListener.php b/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallListener.php
new file mode 100644
index 0000000000000..a27c422fb8d23
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallListener.php
@@ -0,0 +1,59 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\EventListener;
+
+use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\Security\Http\Firewall;
+use Symfony\Component\Security\Http\FirewallMapInterface;
+use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
+
+/**
+ * @author Maxime Steinhausser
+ */
+class FirewallListener extends Firewall
+{
+ private $map;
+ private $logoutUrlGenerator;
+
+ public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher, LogoutUrlGenerator $logoutUrlGenerator)
+ {
+ $this->map = $map;
+ $this->logoutUrlGenerator = $logoutUrlGenerator;
+
+ parent::__construct($map, $dispatcher);
+ }
+
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ if ($this->map instanceof FirewallMap && $config = $this->map->getFirewallConfig($event->getRequest())) {
+ $this->logoutUrlGenerator->setCurrentFirewall($config->getName(), $config->getContext());
+ }
+
+ parent::onKernelRequest($event);
+ }
+
+ public function onKernelFinishRequest(FinishRequestEvent $event)
+ {
+ if ($event->isMasterRequest()) {
+ $this->logoutUrlGenerator->setCurrentFirewall(null);
+ }
+
+ parent::onKernelFinishRequest($event);
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/LICENSE b/src/Symfony/Bundle/SecurityBundle/LICENSE
index 12a74531e40a4..17d16a13367dd 100644
--- a/src/Symfony/Bundle/SecurityBundle/LICENSE
+++ b/src/Symfony/Bundle/SecurityBundle/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2016 Fabien Potencier
+Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml
new file mode 100644
index 0000000000000..12d8e13c67b4a
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index 54e573440299c..9ec300851df81 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -17,8 +17,10 @@
%security.access.always_authenticate_before_granting%
+
+
@@ -27,7 +29,7 @@
-
+
%security.authentication.manager.erase_credentials%
@@ -48,12 +50,14 @@
+
-
+
+
@@ -67,6 +71,7 @@
+
%security.role_hierarchy.roles%
@@ -97,15 +102,17 @@
-
+
+
+
-
-
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml
index 581c938964e67..b8660b4bc554a 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml
@@ -35,6 +35,7 @@
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml
index eb22cbddf504e..e03f578784a33 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml
@@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
index 7bdaf628cf40c..45ebde81f1325 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
@@ -140,7 +140,21 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
index 3830e924a190b..073d0d869d8f0 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
@@ -257,7 +257,13 @@
: 'DENIED '
}}
- {{ decision.attributes|length == 1 ? decision.attributes|first : profiler_dump(decision.attributes) }}
+
+ {% if decision.attributes|length == 1 %}
+ {{ decision.attributes|first }}
+ {% else %}
+ {{ profiler_dump(decision.attributes) }}
+ {% endif %}
+
{{ profiler_dump(decision.object) }}
{% endfor %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
index 81b815e4d973e..02f2739ed8a2f 100644
--- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
+++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
@@ -37,8 +37,23 @@ public function getConfig()
return $this->config;
}
+ /**
+ * @deprecated since version 3.3, will be removed in 4.0. Use {@link getListeners()} and/or {@link getExceptionListener()} instead.
+ */
public function getContext()
{
- return array($this->listeners, $this->exceptionListener);
+ @trigger_error(sprintf('Method %s() is deprecated since version 3.3 and will be removed in 4.0. Use %s::getListeners/getExceptionListener() instead.', __METHOD__, __CLASS__), E_USER_DEPRECATED);
+
+ return array($this->getListeners(), $this->getExceptionListener());
+ }
+
+ public function getListeners()
+ {
+ return $this->listeners;
+ }
+
+ public function getExceptionListener()
+ {
+ return $this->exceptionListener;
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
index f833a63e65966..55272ec3043bd 100644
--- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
+++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
@@ -11,9 +11,9 @@
namespace Symfony\Bundle\SecurityBundle\Security;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Security\Http\FirewallMapInterface;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* This is a lazy-loading firewall map implementation.
@@ -22,22 +22,100 @@
*
* @author Johannes M. Schmitt
*/
-class FirewallMap implements FirewallMapInterface
+class FirewallMap extends _FirewallMap implements FirewallMapInterface
{
- protected $container;
- protected $map;
- private $contexts;
+ /**
+ * @deprecated since version 3.3, to be removed in 4.0 alongside with magic methods below
+ */
+ private $container;
- public function __construct(ContainerInterface $container, array $map)
+ /**
+ * @deprecated since version 3.3, to be removed in 4.0 alongside with magic methods below
+ */
+ private $map;
+
+ public function __construct(ContainerInterface $container, $map)
{
+ parent::__construct($container, $map);
$this->container = $container;
$this->map = $map;
- $this->contexts = new \SplObjectStorage();
}
/**
- * {@inheritdoc}
+ * @internal
*/
+ public function __get($name)
+ {
+ if ('map' === $name || 'container' === $name) {
+ @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED);
+
+ if ('map' === $name && $this->map instanceof \Traversable) {
+ $this->map = iterator_to_array($this->map);
+ }
+ }
+
+ return $this->$name;
+ }
+
+ /**
+ * @internal
+ */
+ public function __set($name, $value)
+ {
+ if ('map' === $name || 'container' === $name) {
+ @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED);
+
+ $set = \Closure::bind(function ($name, $value) { $this->$name = $value; }, $this, parent::class);
+ $set($name, $value);
+ }
+
+ $this->$name = $value;
+ }
+
+ /**
+ * @internal
+ */
+ public function __isset($name)
+ {
+ if ('map' === $name || 'container' === $name) {
+ @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED);
+ }
+
+ return isset($this->$name);
+ }
+
+ /**
+ * @internal
+ */
+ public function __unset($name)
+ {
+ if ('map' === $name || 'container' === $name) {
+ @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED);
+
+ $unset = \Closure::bind(function ($name) { unset($this->$name); }, $this, parent::class);
+ $unset($name);
+ }
+
+ unset($this->$name);
+ }
+}
+
+/**
+ * @internal to be removed in 4.0
+ */
+class _FirewallMap
+{
+ private $container;
+ private $map;
+ private $contexts;
+
+ public function __construct(ContainerInterface $container, $map)
+ {
+ $this->container = $container;
+ $this->map = $map;
+ $this->contexts = new \SplObjectStorage();
+ }
+
public function getListeners(Request $request)
{
$context = $this->getFirewallContext($request);
@@ -46,7 +124,7 @@ public function getListeners(Request $request)
return array(array(), null);
}
- return $context->getContext();
+ return array($context->getListeners(), $context->getExceptionListener());
}
/**
diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
index f2dfc991fbcef..c50aab24e12e4 100644
--- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
+++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginFactory;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
@@ -42,6 +43,7 @@ public function build(ContainerBuilder $container)
$extension = $container->getExtension('security');
$extension->addSecurityListenerFactory(new FormLoginFactory());
$extension->addSecurityListenerFactory(new FormLoginLdapFactory());
+ $extension->addSecurityListenerFactory(new JsonLoginFactory());
$extension->addSecurityListenerFactory(new HttpBasicFactory());
$extension->addSecurityListenerFactory(new HttpBasicLdapFactory());
$extension->addSecurityListenerFactory(new HttpDigestFactory());
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php
index 2d912721ed4f4..f155f901c9c3c 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DataCollector;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
@@ -20,7 +21,7 @@
use Symfony\Component\Security\Core\Role\RoleHierarchy;
use Symfony\Component\Security\Http\FirewallMapInterface;
-class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
+class SecurityDataCollectorTest extends TestCase
{
public function testCollectWhenSecurityIsDisabled()
{
@@ -62,17 +63,14 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
$collector->collect($this->getRequest(), $this->getResponse());
+ $collector->lateCollect();
$this->assertTrue($collector->isEnabled());
$this->assertTrue($collector->isAuthenticated());
- $this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass());
+ $this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass()->getValue());
$this->assertTrue($collector->supportsRoleHierarchy());
- $this->assertSame($normalizedRoles, $collector->getRoles()->getRawData()[1]);
- if ($inheritedRoles) {
- $this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getRawData()[1]);
- } else {
- $this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getRawData()[0][0]);
- }
+ $this->assertSame($normalizedRoles, $collector->getRoles()->getValue(true));
+ $this->assertSame($inheritedRoles, $collector->getInheritedRoles()->getValue(true));
$this->assertSame('hhamon', $collector->getUser());
}
@@ -93,6 +91,7 @@ public function testGetFirewall()
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
$collector->collect($request, $this->getResponse());
+ $collector->lateCollect();
$collected = $collector->getFirewall();
$this->assertSame($firewallConfig->getName(), $collected['name']);
@@ -106,7 +105,7 @@ public function testGetFirewall()
$this->assertSame($firewallConfig->getAccessDeniedHandler(), $collected['access_denied_handler']);
$this->assertSame($firewallConfig->getAccessDeniedUrl(), $collected['access_denied_url']);
$this->assertSame($firewallConfig->getUserChecker(), $collected['user_checker']);
- $this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getRawData()[0][0]);
+ $this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getValue());
}
public function testGetFirewallReturnsNull()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php
new file mode 100644
index 0000000000000..66d6bde205975
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Compiler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+class AddSecurityVotersPassTest extends TestCase
+{
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException
+ */
+ public function testNoVoters()
+ {
+ $container = new ContainerBuilder();
+ $container
+ ->register('security.access.decision_manager', 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager')
+ ->addArgument(array())
+ ;
+
+ $compilerPass = new AddSecurityVotersPass();
+ $compilerPass->process($container);
+ }
+
+ public function testThatSecurityVotersAreProcessedInPriorityOrder()
+ {
+ $container = new ContainerBuilder();
+ $container
+ ->register('security.access.decision_manager', 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager')
+ ->addArgument(array())
+ ;
+ $container
+ ->register('no_prio_service')
+ ->addTag('security.voter')
+ ;
+ $container
+ ->register('lowest_prio_service')
+ ->addTag('security.voter', array('priority' => 100))
+ ;
+ $container
+ ->register('highest_prio_service')
+ ->addTag('security.voter', array('priority' => 200))
+ ;
+ $container
+ ->register('zero_prio_service')
+ ->addTag('security.voter', array('priority' => 0))
+ ;
+ $compilerPass = new AddSecurityVotersPass();
+ $compilerPass->process($container);
+
+ $argument = $container->getDefinition('security.access.decision_manager')->getArgument(0);
+ $refs = $argument->getValues();
+ $this->assertEquals(new Reference('highest_prio_service'), $refs[0]);
+ $this->assertEquals(new Reference('lowest_prio_service'), $refs[1]);
+ $this->assertCount(4, $refs);
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
index bbce61a75813b..bfa0f1b877b28 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
+abstract class CompleteConfigurationTest extends TestCase
{
private static $containerCache = array();
@@ -68,12 +69,12 @@ public function testFirewalls()
$arguments = $container->getDefinition('security.firewall.map')->getArguments();
$listeners = array();
$configs = array();
- foreach (array_keys($arguments[1]) as $contextId) {
+ foreach (array_keys($arguments[1]->getValues()) as $contextId) {
$contextDef = $container->getDefinition($contextId);
$arguments = $contextDef->getArguments();
- $listeners[] = array_map(function ($ref) { return (string) $ref; }, $arguments['index_0']);
+ $listeners[] = array_map('strval', $arguments['index_0']);
- $configDef = $container->getDefinition($arguments['index_2']);
+ $configDef = $container->getDefinition((string) $arguments['index_2']);
$configs[] = array_values($configDef->getArguments());
}
@@ -171,6 +172,8 @@ public function testFirewalls()
'security.access_listener',
),
), $listeners);
+
+ $this->assertFalse($container->hasAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', 'No user checker alias is registered when custom user checker services are registered'));
}
public function testFirewallRequestMatchers()
@@ -180,7 +183,7 @@ public function testFirewallRequestMatchers()
$arguments = $container->getDefinition('security.firewall.map')->getArguments();
$matchers = array();
- foreach ($arguments[1] as $reference) {
+ foreach ($arguments[1]->getValues() as $reference) {
if ($reference instanceof Reference) {
$definition = $container->getDefinition((string) $reference);
$matchers[] = $definition->getArguments();
@@ -199,6 +202,14 @@ public function testFirewallRequestMatchers()
), $matchers);
}
+ public function testUserCheckerAliasIsRegistered()
+ {
+ $container = $this->getContainer('no_custom_user_checker');
+
+ $this->assertTrue($container->hasAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', 'Alias for user checker is registered when no custom user checker service is registered'));
+ $this->assertFalse($container->getAlias('Symfony\Component\Security\Core\User\UserCheckerInterface')->isPublic());
+ }
+
public function testAccess()
{
$container = $this->getContainer('container1');
@@ -234,7 +245,7 @@ public function testAccess()
);
} elseif (3 === $i) {
$this->assertEquals('IS_AUTHENTICATED_ANONYMOUSLY', $attributes[0]);
- $expression = $container->getDefinition($attributes[1])->getArgument(0);
+ $expression = $container->getDefinition((string) $attributes[1])->getArgument(0);
$this->assertEquals("token.getUsername() matches '/^admin/'", $expression);
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php
new file mode 100644
index 0000000000000..b08d9c60c82f8
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php
@@ -0,0 +1,28 @@
+loadFromExtension('security', array(
+ 'providers' => array(
+ 'default' => array(
+ 'memory' => array(
+ 'users' => array(
+ 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
+ ),
+ ),
+ ),
+ ),
+ 'firewalls' => array(
+ 'simple' => array('pattern' => '/login', 'security' => false),
+ 'secure' => array('stateless' => true,
+ 'http_basic' => true,
+ 'http_digest' => array('secret' => 'TheSecret'),
+ 'form_login' => true,
+ 'anonymous' => true,
+ 'switch_user' => true,
+ 'x509' => true,
+ 'remote_user' => true,
+ 'logout' => true,
+ 'remember_me' => array('secret' => 'TheSecret'),
+ 'user_checker' => null,
+ ),
+ ),
+));
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml
new file mode 100644
index 0000000000000..7d648ae1baec2
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml
new file mode 100644
index 0000000000000..23afa8cd9b3c5
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml
@@ -0,0 +1,23 @@
+security:
+ providers:
+ default:
+ memory:
+ users:
+ foo: { password: foo, roles: ROLE_USER }
+
+ firewalls:
+ simple: { pattern: /login, security: false }
+ secure:
+ stateless: true
+ http_basic: true
+ http_digest:
+ secret: TheSecret
+ form_login: true
+ anonymous: true
+ switch_user: true
+ x509: true
+ remote_user: true
+ logout: true
+ remember_me:
+ secret: TheSecret
+ user_checker: ~
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php
index 8a8f5c8329dea..a64c4fe4101f1 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\DependencyInjection\MainConfiguration;
use Symfony\Component\Config\Definition\Processor;
-class MainConfigurationTest extends \PHPUnit_Framework_TestCase
+class MainConfigurationTest extends TestCase
{
/**
* The minimal, required config needed to not have any required validation
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php
index 39daf998cb4e7..846d76f770d59 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php
@@ -11,10 +11,11 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory;
+use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
+class AbstractFactoryTest extends TestCase
{
public function testCreate()
{
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php
index 4c1634850275c..55a3ad387c224 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php
@@ -11,12 +11,14 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\GuardAuthenticationFactory;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
-class GuardAuthenticationFactoryTest extends \PHPUnit_Framework_TestCase
+class GuardAuthenticationFactoryTest extends TestCase
{
/**
* @dataProvider getValidConfigurationTests
@@ -106,7 +108,7 @@ public function testBasicCreate()
$providerDefinition = $container->getDefinition('security.authentication.provider.guard.my_firewall');
$this->assertEquals(array(
- 'index_0' => array(new Reference('authenticator123')),
+ 'index_0' => new IteratorArgument(array(new Reference('authenticator123'))),
'index_1' => new Reference('my_user_provider'),
'index_2' => 'my_firewall',
'index_3' => new Reference('security.user_checker.my_firewall'),
@@ -114,7 +116,7 @@ public function testBasicCreate()
$listenerDefinition = $container->getDefinition('security.authentication.listener.guard.my_firewall');
$this->assertEquals('my_firewall', $listenerDefinition->getArgument(2));
- $this->assertEquals(array(new Reference('authenticator123')), $listenerDefinition->getArgument(3));
+ $this->assertEquals(array(new Reference('authenticator123')), $listenerDefinition->getArgument(3)->getValues());
}
public function testExistingDefaultEntryPointUsed()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php
index dce30c758b976..72ef2e0c3ed56 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php
@@ -11,12 +11,13 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
+class SecurityExtensionTest extends TestCase
{
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AutowiringTypesTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AutowiringTypesTest.php
new file mode 100644
index 0000000000000..a0bee3c01c1ca
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AutowiringTypesTest.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
+
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
+use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
+
+class AutowiringTypesTest extends WebTestCase
+{
+ public function testAccessDecisionManagerAutowiring()
+ {
+ static::bootKernel(array('debug' => false));
+ $container = static::$kernel->getContainer();
+
+ $autowiredServices = $container->get('test.autowiring_types.autowired_services');
+ $this->assertInstanceOf(AccessDecisionManager::class, $autowiredServices->getAccessDecisionManager(), 'The security.access.decision_manager service should be injected in debug mode');
+
+ static::bootKernel(array('debug' => true));
+ $container = static::$kernel->getContainer();
+
+ $autowiredServices = $container->get('test.autowiring_types.autowired_services');
+ $this->assertInstanceOf(TraceableAccessDecisionManager::class, $autowiredServices->getAccessDecisionManager(), 'The debug.security.access.decision_manager service should be injected in non-debug mode');
+ }
+
+ protected static function createKernel(array $options = array())
+ {
+ return parent::createKernel(array('test_case' => 'AutowiringTypes') + $options);
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiredServices.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiredServices.php
new file mode 100644
index 0000000000000..30aa62f1f66ec
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiredServices.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle;
+
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
+
+class AutowiredServices
+{
+ private $accessDecisionManager;
+
+ public function __construct(AccessDecisionManagerInterface $accessDecisionManager)
+ {
+ $this->accessDecisionManager = $accessDecisionManager;
+ }
+
+ public function getAccessDecisionManager()
+ {
+ return $this->accessDecisionManager;
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiringBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiringBundle.php
new file mode 100644
index 0000000000000..d57031a018fe9
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AutowiringBundle/AutowiringBundle.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class AutowiringBundle extends Bundle
+{
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
index c232b4cfd9029..90f4d355a4871 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
@@ -24,14 +24,14 @@ public function loginAction()
{
$form = $this->container->get('form.factory')->create('Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\Form\UserLoginType');
- return $this->container->get('templating')->renderResponse('CsrfFormLoginBundle:Login:login.html.twig', array(
+ return new Response($this->container->get('twig')->render('@CsrfFormLogin/Login/login.html.twig', array(
'form' => $form->createView(),
- ));
+ )));
}
public function afterLoginAction()
{
- return $this->container->get('templating')->renderResponse('CsrfFormLoginBundle:Login:after_login.html.twig');
+ return new Response($this->container->get('twig')->render('@CsrfFormLogin/Login/after_login.html.twig'));
}
public function loginCheckAction()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/after_login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/after_login.html.twig
index b56c186ecbb60..a117cb94f8778 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/after_login.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/after_login.html.twig
@@ -1,4 +1,4 @@
-{% extends "::base.html.twig" %}
+{% extends "base.html.twig" %}
{% block body %}
Hello {{ app.user.username }}!
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/login.html.twig
index 36ae0151d0d00..a21ea7259b1b5 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/login.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Resources/views/Login/login.html.twig
@@ -1,4 +1,4 @@
-{% extends "::base.html.twig" %}
+{% extends "base.html.twig" %}
{% block body %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php
index 7a6faf4cc99d2..f8b4d9068f7b1 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php
@@ -30,11 +30,11 @@ public function loginAction(Request $request)
$error = $request->getSession()->get(Security::AUTHENTICATION_ERROR);
}
- return $this->container->get('templating')->renderResponse('FormLoginBundle:Localized:login.html.twig', array(
+ return new Response($this->container->get('twig')->render('@FormLogin/Localized/login.html.twig', array(
// last username entered by the user
'last_username' => $request->getSession()->get(Security::LAST_USERNAME),
'error' => $error,
- ));
+ )));
}
public function loginCheckAction()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
index acc8f43255494..658a3cd57c24f 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
@@ -32,16 +32,16 @@ public function loginAction(Request $request, UserInterface $user = null)
$error = $request->getSession()->get(Security::AUTHENTICATION_ERROR);
}
- return $this->container->get('templating')->renderResponse('FormLoginBundle:Login:login.html.twig', array(
+ return new Response($this->container->get('twig')->render('@FormLogin/Login/login.html.twig', array(
// last username entered by the user
'last_username' => $request->getSession()->get(Security::LAST_USERNAME),
'error' => $error,
- ));
+ )));
}
public function afterLoginAction(UserInterface $user)
{
- return $this->container->get('templating')->renderResponse('FormLoginBundle:Login:after_login.html.twig', array('user' => $user));
+ return new Response($this->container->get('twig')->render('@FormLogin/Login/after_login.html.twig', array('user' => $user)));
}
public function loginCheckAction()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig
index 60dd2f1ffac7b..de0da3bb589c0 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig
@@ -1,4 +1,4 @@
-{% extends "::base.html.twig" %}
+{% extends "base.html.twig" %}
{% block body %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig
index 8f6a76098597f..3f88aae903536 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig
@@ -1,4 +1,4 @@
-{% extends "::base.html.twig" %}
+{% extends "base.html.twig" %}
{% block body %}
Hello {{ user.username }}!
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/login.html.twig
index 6c1a22471e10c..059f5f2bca1d2 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/login.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/login.html.twig
@@ -1,4 +1,4 @@
-{% extends "::base.html.twig" %}
+{% extends "base.html.twig" %}
{% block body %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Controller/TestController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Controller/TestController.php
new file mode 100644
index 0000000000000..3effab9b59913
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Controller/TestController.php
@@ -0,0 +1,26 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\Controller;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\Security\Core\User\UserInterface;
+
+/**
+ * @author Kévin Dunglas
+ */
+class TestController
+{
+ public function loginCheckAction(UserInterface $user)
+ {
+ return new JsonResponse(array('message' => sprintf('Welcome @%s!', $user->getUsername())));
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/JsonLoginBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/JsonLoginBundle.php
new file mode 100644
index 0000000000000..88b57859ad24c
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/JsonLoginBundle.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * @author Kévin Dunglas
+ */
+class JsonLoginBundle extends Bundle
+{
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationFailureHandler.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationFailureHandler.php
new file mode 100644
index 0000000000000..fbd482ddffeb0
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationFailureHandler.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\Security\Http;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
+
+class JsonAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
+{
+ public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
+ {
+ return new JsonResponse(array('message' => 'Something went wrong'), 500);
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationSuccessHandler.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationSuccessHandler.php
new file mode 100644
index 0000000000000..0e65bbb56b98a
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/JsonLoginBundle/Security/Http/JsonAuthenticationSuccessHandler.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\Security\Http;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
+
+class JsonAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
+{
+ public function onAuthenticationSuccess(Request $request, TokenInterface $token)
+ {
+ return new JsonResponse(array('message' => sprintf('Good game @%s!', $token->getUsername())));
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php
index 80211f5251b08..2d95d35065137 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php
@@ -108,14 +108,4 @@ public function getConfigs()
array('routes_as_path.yml'),
);
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('CsrfFormLogin');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('CsrfFormLogin');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php
index 30d0935ffddd7..8179c2e942a6c 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FirewallEntryPointTest.php
@@ -43,14 +43,4 @@ public function testItUsesTheConfiguredEntryPointFromTheExceptionListenerWithFor
"Custom entry point wasn't started"
);
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('FirewallEntryPoint');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('FirewallEntryPoint');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
index 2f19f3f8a1a9a..c2e766e9acca1 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
@@ -113,14 +113,4 @@ public function getConfigs()
array('routes_as_path.yml'),
);
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginTest.php
new file mode 100644
index 0000000000000..7ee4c9b25dd45
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginTest.php
@@ -0,0 +1,75 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * @author Kévin Dunglas
+ */
+class JsonLoginTest extends WebTestCase
+{
+ public function testDefaultJsonLoginSuccess()
+ {
+ $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'config.yml'));
+ $client->request('POST', '/chk', array(), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "dunglas", "password": "foo"}}');
+ $response = $client->getResponse();
+
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ $this->assertSame(array('message' => 'Welcome @dunglas!'), json_decode($response->getContent(), true));
+ }
+
+ public function testDefaultJsonLoginFailure()
+ {
+ $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'config.yml'));
+ $client->request('POST', '/chk', array(), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "dunglas", "password": "bad"}}');
+ $response = $client->getResponse();
+
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertSame(401, $response->getStatusCode());
+ $this->assertSame(array('error' => 'Invalid credentials.'), json_decode($response->getContent(), true));
+ }
+
+ public function testCustomJsonLoginSuccess()
+ {
+ $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'custom_handlers.yml'));
+ $client->request('POST', '/chk', array(), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "dunglas", "password": "foo"}}');
+ $response = $client->getResponse();
+
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertSame(200, $response->getStatusCode());
+ $this->assertSame(array('message' => 'Good game @dunglas!'), json_decode($response->getContent(), true));
+ }
+
+ public function testCustomJsonLoginFailure()
+ {
+ $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'custom_handlers.yml'));
+ $client->request('POST', '/chk', array(), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "dunglas", "password": "bad"}}');
+ $response = $client->getResponse();
+
+ $this->assertInstanceOf(JsonResponse::class, $response);
+ $this->assertSame(500, $response->getStatusCode());
+ $this->assertSame(array('message' => 'Something went wrong'), json_decode($response->getContent(), true));
+ }
+
+ public function testDefaultJsonLoginBadRequest()
+ {
+ $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'config.yml'));
+ $client->request('POST', '/chk', array(), array(), array('CONTENT_TYPE' => 'application/json'), 'Not a json content');
+ $response = $client->getResponse();
+
+ $this->assertSame(400, $response->getStatusCode());
+ $this->assertSame('application/json', $response->headers->get('Content-Type'));
+ $this->assertArraySubset(array('error' => array('code' => 400, 'message' => 'Bad Request')), json_decode($response->getContent(), true));
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php
index 14c317966e21a..cb600764eaf42 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php
@@ -76,14 +76,4 @@ public function getLocales()
{
return array(array('en'), array('de'));
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
index c7db437819a1c..3abfd9585f159 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
@@ -116,14 +116,4 @@ public function getConfigs()
{
return array(array('config.yml'), array('routes_as_path.yml'));
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php
index db4c51c5f064d..3b060a86fc242 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php
@@ -40,20 +40,9 @@ class SetAclCommandTest extends WebTestCase
const OBJECT_CLASS = 'Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\Entity\Car';
const SECURITY_CLASS = 'Symfony\Component\Security\Core\User\User';
- protected function setUp()
- {
- parent::setUp();
-
- $this->deleteTmpDir('Acl');
- }
-
- protected function tearDown()
- {
- parent::tearDown();
-
- $this->deleteTmpDir('Acl');
- }
-
+ /**
+ * @group legacy
+ */
public function testSetAclUser()
{
$objectId = 1;
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php
index e5079c3283aac..f12e95671be2c 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php
@@ -70,14 +70,4 @@ protected function createAuthenticatedClient($username)
return $client;
}
-
- public static function setUpBeforeClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
-
- public static function tearDownAfterClass()
- {
- parent::deleteTmpDir('StandardFormLogin');
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php
index b1c75bfedd755..0710f94b5b094 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php
@@ -13,8 +13,10 @@
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand;
+use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
+use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
/**
@@ -24,6 +26,7 @@
*/
class UserPasswordEncoderCommandTest extends WebTestCase
{
+ /** @var CommandTester */
private $passwordEncoderCommandTester;
public function testEncodePasswordEmptySalt()
@@ -105,6 +108,7 @@ public function testEncodePasswordEmptySaltOutput()
array(
'command' => 'security:encode-password',
'password' => 'p@ssw0rd',
+ 'user-class' => 'Symfony\Component\Security\Core\User\User',
'--empty-salt' => true,
)
);
@@ -129,7 +133,12 @@ public function testEncodePasswordBcryptOutput()
public function testEncodePasswordNoConfigForGivenUserClass()
{
- $this->setExpectedException('\RuntimeException', 'No encoder has been configured for account "Foo\Bar\User".');
+ if (method_exists($this, 'expectException')) {
+ $this->expectException('\RuntimeException');
+ $this->expectExceptionMessage('No encoder has been configured for account "Foo\Bar\User".');
+ } else {
+ $this->setExpectedException('\RuntimeException', 'No encoder has been configured for account "Foo\Bar\User".');
+ }
$this->passwordEncoderCommandTester->execute(array(
'command' => 'security:encode-password',
@@ -138,6 +147,74 @@ public function testEncodePasswordNoConfigForGivenUserClass()
), array('interactive' => false));
}
+ public function testEncodePasswordAsksNonProvidedUserClass()
+ {
+ $this->passwordEncoderCommandTester->setInputs(array('Custom\Class\Pbkdf2\User', "\n"));
+ $this->passwordEncoderCommandTester->execute(array(
+ 'command' => 'security:encode-password',
+ 'password' => 'password',
+ ), array('decorated' => false));
+
+ $this->assertContains(<<passwordEncoderCommandTester->getDisplay(true));
+ }
+
+ public function testNonInteractiveEncodePasswordUsesFirstUserClass()
+ {
+ $this->passwordEncoderCommandTester->execute(array(
+ 'command' => 'security:encode-password',
+ 'password' => 'password',
+ ), array('interactive' => false));
+
+ $this->assertContains('Encoder used Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder', $this->passwordEncoderCommandTester->getDisplay());
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage There are no configured encoders for the "security" extension.
+ */
+ public function testThrowsExceptionOnNoConfiguredEncoders()
+ {
+ $application = new ConsoleApplication();
+ $application->add(new UserPasswordEncoderCommand($this->getMockBuilder(EncoderFactoryInterface::class)->getMock(), array()));
+
+ $passwordEncoderCommand = $application->find('security:encode-password');
+
+ $tester = new CommandTester($passwordEncoderCommand);
+ $tester->execute(array(
+ 'command' => 'security:encode-password',
+ 'password' => 'password',
+ ), array('interactive' => false));
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Passing null as the first argument of "Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand::__construct" is deprecated since version 3.3 and will be removed in 4.0. If the command was registered by convention, make it a service instead.
+ */
+ public function testLegacy()
+ {
+ $application = new ConsoleApplication();
+ $application->add(new UserPasswordEncoderCommand());
+
+ $passwordEncoderCommand = $application->find('security:encode-password');
+ self::bootKernel(array('test_case' => 'PasswordEncode'));
+ $passwordEncoderCommand->setContainer(self::$kernel->getContainer());
+
+ $tester = new CommandTester($passwordEncoderCommand);
+ $tester->execute(array(
+ 'command' => 'security:encode-password',
+ 'password' => 'password',
+ ), array('interactive' => false));
+
+ $this->assertContains('Encoder used Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder', $tester->getDisplay());
+ }
+
protected function setUp()
{
putenv('COLUMNS='.(119 + strlen(PHP_EOL)));
@@ -146,8 +223,7 @@ protected function setUp()
$application = new Application($kernel);
- $application->add(new UserPasswordEncoderCommand());
- $passwordEncoderCommand = $application->find('security:encode-password');
+ $passwordEncoderCommand = $application->get('security:encode-password');
$this->passwordEncoderCommandTester = new CommandTester($passwordEncoderCommand);
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
index 33da9028a3daf..8bace799a37a8 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
@@ -13,7 +13,6 @@
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase;
use Symfony\Component\Filesystem\Filesystem;
-use Symfony\Component\HttpKernel\Kernel;
class WebTestCase extends BaseWebTestCase
{
@@ -23,9 +22,19 @@ public static function assertRedirect($response, $location)
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
}
- protected static function deleteTmpDir($testCase)
+ public static function setUpBeforeClass()
{
- if (!file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$testCase)) {
+ static::deleteTmpDir();
+ }
+
+ public static function tearDownAfterClass()
+ {
+ static::deleteTmpDir();
+ }
+
+ protected static function deleteTmpDir()
+ {
+ if (!file_exists($dir = sys_get_temp_dir().'/'.static::getVarDir())) {
return;
}
@@ -49,10 +58,16 @@ protected static function createKernel(array $options = array())
}
return new $class(
+ static::getVarDir(),
$options['test_case'],
isset($options['root_config']) ? $options['root_config'] : 'config.yml',
- isset($options['environment']) ? $options['environment'] : 'securitybundletest'.strtolower($options['test_case']),
+ isset($options['environment']) ? $options['environment'] : strtolower(static::getVarDir().$options['test_case']),
isset($options['debug']) ? $options['debug'] : true
);
}
+
+ protected static function getVarDir()
+ {
+ return substr(strrchr(get_called_class(), '\\'), 1);
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
index b828c5acfd91b..1aab514f45450 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
@@ -11,30 +11,6 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app;
-// get the autoload file
-$dir = __DIR__;
-$lastDir = null;
-while ($dir !== $lastDir) {
- $lastDir = $dir;
-
- if (is_file($dir.'/autoload.php')) {
- require_once $dir.'/autoload.php';
- break;
- }
-
- if (is_file($dir.'/autoload.php.dist')) {
- require_once $dir.'/autoload.php.dist';
- break;
- }
-
- if (file_exists($dir.'/vendor/autoload.php')) {
- require_once $dir.'/vendor/autoload.php';
- break;
- }
-
- $dir = dirname($dir);
-}
-
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Kernel;
@@ -46,14 +22,16 @@
*/
class AppKernel extends Kernel
{
+ private $varDir;
private $testCase;
private $rootConfig;
- public function __construct($testCase, $rootConfig, $environment, $debug)
+ public function __construct($varDir, $testCase, $rootConfig, $environment, $debug)
{
if (!is_dir(__DIR__.'/'.$testCase)) {
throw new \InvalidArgumentException(sprintf('The test case "%s" does not exist.', $testCase));
}
+ $this->varDir = $varDir;
$this->testCase = $testCase;
$fs = new Filesystem();
@@ -71,7 +49,7 @@ public function __construct($testCase, $rootConfig, $environment, $debug)
public function getName()
{
if (null === $this->name) {
- $this->name = parent::getName().md5($this->rootConfig);
+ $this->name = parent::getName().substr(md5($this->rootConfig), -16);
}
return $this->name;
@@ -93,12 +71,12 @@ public function getRootDir()
public function getCacheDir()
{
- return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/cache/'.$this->environment;
+ return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/cache/'.$this->environment;
}
public function getLogDir()
{
- return sys_get_temp_dir().'/'.Kernel::VERSION.'/'.$this->testCase.'/logs';
+ return sys_get_temp_dir().'/'.$this->varDir.'/'.$this->testCase.'/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
@@ -108,13 +86,13 @@ public function registerContainerConfiguration(LoaderInterface $loader)
public function serialize()
{
- return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
+ return serialize(array($this->varDir, $this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
}
public function unserialize($str)
{
$a = unserialize($str);
- $this->__construct($a[0], $a[1], $a[2], $a[3]);
+ $this->__construct($a[0], $a[1], $a[2], $a[3], $a[4]);
}
protected function getKernelParameters()
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php
new file mode 100644
index 0000000000000..68e5afb125f85
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php
@@ -0,0 +1,16 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
+ new Symfony\Bundle\SecurityBundle\SecurityBundle(),
+ new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiringBundle(),
+);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml
new file mode 100644
index 0000000000000..bb3ef5a2dc70f
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml
@@ -0,0 +1,14 @@
+imports:
+ - { resource: ../config/framework.yml }
+
+services:
+ test.autowiring_types.autowired_services:
+ class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiredServices
+ autowire: true
+security:
+ providers:
+ dummy:
+ memory: ~
+ firewalls:
+ dummy:
+ security: false
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php
new file mode 100644
index 0000000000000..470ffff088cd9
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php
@@ -0,0 +1,17 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ new Symfony\Bundle\SecurityBundle\SecurityBundle(),
+ new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
+ new Symfony\Bundle\TwigBundle\TwigBundle(),
+ new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\JsonLoginBundle(),
+);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml
new file mode 100644
index 0000000000000..d6ed10e896ff9
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml
@@ -0,0 +1,24 @@
+imports:
+ - { resource: ./../config/framework.yml }
+
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ providers:
+ in_memory:
+ memory:
+ users:
+ dunglas: { password: foo, roles: [ROLE_USER] }
+
+ firewalls:
+ main:
+ pattern: ^/
+ anonymous: true
+ json_login:
+ check_path: /chk
+ username_path: user.login
+ password_path: user.password
+
+ access_control:
+ - { path: ^/foo, roles: ROLE_USER }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/custom_handlers.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/custom_handlers.yml
new file mode 100644
index 0000000000000..e15e203c626cc
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/custom_handlers.yml
@@ -0,0 +1,32 @@
+imports:
+ - { resource: ./../config/framework.yml }
+
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ providers:
+ in_memory:
+ memory:
+ users:
+ dunglas: { password: foo, roles: [ROLE_USER] }
+
+ firewalls:
+ main:
+ pattern: ^/
+ anonymous: true
+ json_login:
+ check_path: /chk
+ username_path: user.login
+ password_path: user.password
+ success_handler: json_login.success_handler
+ failure_handler: json_login.failure_handler
+
+ access_control:
+ - { path: ^/foo, roles: ROLE_USER }
+
+services:
+ json_login.success_handler:
+ class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\Security\Http\JsonAuthenticationSuccessHandler
+ json_login.failure_handler:
+ class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\Security\Http\JsonAuthenticationFailureHandler
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/routing.yml
new file mode 100644
index 0000000000000..ee49b4829bdd7
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/routing.yml
@@ -0,0 +1,3 @@
+login_check:
+ path: /chk
+ defaults: { _controller: JsonLoginBundle:Test:loginCheck }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml
index 61c1a54d99ba5..493989866a278 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml
@@ -1,6 +1,3 @@
-framework:
- templating: { engines: ['twig'] }
-
# Twig Configuration
twig:
debug: '%kernel.debug%'
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php
index a6fdeeed3768a..a0b4a79c50cdc 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php
@@ -11,9 +11,10 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Security;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
-class FirewallConfigTest extends \PHPUnit_Framework_TestCase
+class FirewallConfigTest extends TestCase
{
public function testGetters()
{
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
index e0790bf23c776..22be0fd081655 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
@@ -11,22 +11,18 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Security;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
-class FirewallContextTest extends \PHPUnit_Framework_TestCase
+class FirewallContextTest extends TestCase
{
public function testGetters()
{
$config = new FirewallConfig('main', 'user_checker', 'request_matcher');
-
- $exceptionListener = $this
- ->getMockBuilder(ExceptionListener::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $exceptionListener = $this->getExceptionListenerMock();
$listeners = array(
$this
->getMockBuilder(ListenerInterface::class)
@@ -36,7 +32,28 @@ public function testGetters()
$context = new FirewallContext($listeners, $exceptionListener, $config);
- $this->assertEquals(array($listeners, $exceptionListener), $context->getContext());
+ $this->assertEquals($listeners, $context->getListeners());
+ $this->assertEquals($exceptionListener, $context->getExceptionListener());
$this->assertEquals($config, $context->getConfig());
}
+
+ /**
+ * @expectedDeprecation Method Symfony\Bundle\SecurityBundle\Security\FirewallContext::getContext() is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Bundle\SecurityBundle\Security\FirewallContext::getListeners/getExceptionListener() instead.
+ * @group legacy
+ */
+ public function testGetContext()
+ {
+ $context = (new FirewallContext($listeners = array(), $exceptionListener = $this->getExceptionListenerMock(), new FirewallConfig('main', 'request_matcher', 'user_checker')))
+ ->getContext();
+
+ $this->assertEquals(array($listeners, $exceptionListener), $context);
+ }
+
+ private function getExceptionListenerMock()
+ {
+ return $this
+ ->getMockBuilder(ExceptionListener::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityUserValueResolverTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityUserValueResolverTest.php
index e0d626a8cee40..0f9a0fe80b646 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityUserValueResolverTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityUserValueResolverTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests;
+use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\SecurityUserValueResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
@@ -20,7 +21,7 @@
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
-class SecurityUserValueResolverTest extends \PHPUnit_Framework_TestCase
+class SecurityUserValueResolverTest extends TestCase
{
public function testResolveNoToken()
{
@@ -33,8 +34,8 @@ public function testResolveNoToken()
public function testResolveNoUser()
{
- $mock = $this->getMock(UserInterface::class);
- $token = $this->getMock(TokenInterface::class);
+ $mock = $this->getMockBuilder(UserInterface::class)->getMock();
+ $token = $this->getMockBuilder(TokenInterface::class)->getMock();
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
@@ -55,8 +56,8 @@ public function testResolveWrongType()
public function testResolve()
{
- $user = $this->getMock(UserInterface::class);
- $token = $this->getMock(TokenInterface::class);
+ $user = $this->getMockBuilder(UserInterface::class)->getMock();
+ $token = $this->getMockBuilder(TokenInterface::class)->getMock();
$token->expects($this->any())->method('getUser')->willReturn($user);
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
@@ -70,8 +71,8 @@ public function testResolve()
public function testIntegration()
{
- $user = $this->getMock(UserInterface::class);
- $token = $this->getMock(TokenInterface::class);
+ $user = $this->getMockBuilder(UserInterface::class)->getMock();
+ $token = $this->getMockBuilder(TokenInterface::class)->getMock();
$token->expects($this->any())->method('getUser')->willReturn($user);
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
@@ -82,7 +83,7 @@ public function testIntegration()
public function testIntegrationNoUser()
{
- $token = $this->getMock(TokenInterface::class);
+ $token = $this->getMockBuilder(TokenInterface::class)->getMock();
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index 132093452fe33..841fc3ea5d6b8 100644
--- a/src/Symfony/Bundle/SecurityBundle/composer.json
+++ b/src/Symfony/Bundle/SecurityBundle/composer.json
@@ -17,31 +17,35 @@
],
"require": {
"php": ">=5.5.9",
- "symfony/security": "~3.2",
- "symfony/http-kernel": "~3.2",
+ "symfony/security": "~3.3",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/http-kernel": "~3.3",
"symfony/polyfill-php70": "~1.0"
},
"require-dev": {
"symfony/asset": "~2.8|~3.0",
"symfony/browser-kit": "~2.8|~3.0",
- "symfony/console": "~2.8|~3.0",
+ "symfony/console": "~3.2",
"symfony/css-selector": "~2.8|~3.0",
"symfony/dom-crawler": "~2.8|~3.0",
- "symfony/form": "~2.8|~3.0",
- "symfony/framework-bundle": "~3.1",
+ "symfony/form": "^2.8.18|^3.2.5",
+ "symfony/framework-bundle": "^3.2.8",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/security-acl": "~2.8|~3.0",
- "symfony/templating": "~2.8|~3.0",
+ "symfony/translation": "~2.8|~3.0",
"symfony/twig-bundle": "~2.8|~3.0",
"symfony/twig-bridge": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0",
- "symfony/validator": "~2.8|~3.0",
- "symfony/var-dumper": "~3.2",
+ "symfony/validator": "^3.2.5",
+ "symfony/var-dumper": "~3.3",
"symfony/yaml": "~2.8|~3.0",
"symfony/expression-language": "~2.8|~3.0",
"doctrine/doctrine-bundle": "~1.4",
"twig/twig": "~1.28|~2.0"
},
+ "conflict": {
+ "symfony/var-dumper": "<3.3"
+ },
"suggest": {
"symfony/security-acl": "For using the ACL functionality of this bundle"
},
@@ -54,7 +58,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "3.3-dev"
}
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist b/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist
index a7fdc326c4571..8636f70c187a5 100644
--- a/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist
+++ b/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist
@@ -5,6 +5,8 @@
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
>
diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md
index 90f7cbd1e0178..9f666dbc29dd7 100644
--- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+3.3.0
+-----
+
+ * Deprecated `ContainerAwareRuntimeLoader`
+
2.7.0
-----
diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
index 9eea901f6dde4..22184833f0eae 100644
--- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
+++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
@@ -11,9 +11,10 @@
namespace Symfony\Bundle\TwigBundle\CacheWarmer;
+use Psr\Container\ContainerInterface;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinderInterface;
use Symfony\Component\Templating\TemplateReference;
@@ -25,7 +26,7 @@
*
* @author Fabien Potencier
*/
-class TemplateCacheCacheWarmer implements CacheWarmerInterface
+class TemplateCacheCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface
{
protected $container;
protected $finder;
@@ -92,6 +93,16 @@ public function isOptional()
return true;
}
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedServices()
+ {
+ return array(
+ 'twig' => \Twig_Environment::class,
+ );
+ }
+
/**
* Find templates in the given directory.
*
diff --git a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php
index 780454aed986e..e2988f3aae5e0 100644
--- a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php
+++ b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php
@@ -11,6 +11,8 @@
namespace Symfony\Bundle\TwigBundle;
+@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use the Twig_ContainerRuntimeLoader class instead.', ContainerAwareRuntimeLoader::class), E_USER_DEPRECATED);
+
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -18,6 +20,8 @@
* Loads Twig extension runtimes via the service container.
*
* @author Fabien Potencier
+ *
+ * @deprecated since version 3.3, will be removed in 4.0. Use \Twig_ContainerRuntimeLoader instead.
*/
class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface
{
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php
index 9fbfd65950a53..b7ebb2a406512 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php
@@ -27,8 +27,10 @@ public function process(ContainerBuilder $container)
return;
}
- // register the exception controller only if Twig is enabled
- if ($container->hasParameter('templating.engines')) {
+ // register the exception controller only if Twig is enabled and required dependencies do exist
+ if (!class_exists('Symfony\Component\Debug\Exception\FlattenException') || !interface_exists('Symfony\Component\EventDispatcher\EventSubscriberInterface')) {
+ $container->removeDefinition('twig.exception_listener');
+ } elseif ($container->hasParameter('templating.engines')) {
$engines = $container->getParameter('templating.engines');
if (!in_array('twig', $engines)) {
$container->removeDefinition('twig.exception_listener');
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
index 603cbe8e22ef1..3e23f5a8a802f 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
@@ -11,13 +11,10 @@
namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;
-use Symfony\Component\Config\Resource\ClassExistenceResource;
+use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
-use Symfony\Component\Stopwatch\Stopwatch;
-use Symfony\Component\Yaml\Parser as YamlParser;
/**
* @author Jean-François Simon
@@ -26,10 +23,29 @@ class ExtensionPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
+ if (!class_exists('Symfony\Component\Asset\Packages')) {
+ $container->removeDefinition('twig.extension.assets');
+ }
+
+ if (!class_exists('Symfony\Component\ExpressionLanguage\Expression')) {
+ $container->removeDefinition('twig.extension.expression');
+ }
+
+ if (!interface_exists('Symfony\Component\Routing\Generator\UrlGeneratorInterface')) {
+ $container->removeDefinition('twig.extension.routing');
+ }
+ if (!interface_exists('Symfony\Component\Translation\TranslatorInterface')) {
+ $container->removeDefinition('twig.extension.trans');
+ }
+
+ if (!class_exists('Symfony\Component\Yaml\Yaml')) {
+ $container->removeDefinition('twig.extension.yaml');
+ }
+
if ($container->has('form.extension')) {
$container->getDefinition('twig.extension.form')->addTag('twig.extension');
$reflClass = new \ReflectionClass('Symfony\Bridge\Twig\Extension\FormExtension');
- $container->getDefinition('twig.loader.filesystem')->addMethodCall('addPath', array(dirname(dirname($reflClass->getFileName())).'/Resources/views/Form'));
+ $container->getDefinition('twig.loader.native_filesystem')->addMethodCall('addPath', array(dirname(dirname($reflClass->getFileName())).'/Resources/views/Form'));
}
if ($container->has('translator')) {
@@ -64,46 +80,30 @@ public function process(ContainerBuilder $container)
$container->getDefinition('twig.extension.debug')->addTag('twig.extension');
}
- if (!$container->has('templating')) {
- $loader = $container->getDefinition('twig.loader.native_filesystem');
- $loader->replaceArgument(1, $this->getComposerRootDir($container->getParameter('kernel.root_dir')));
- $loader->addTag('twig.loader');
- $loader->setMethodCalls($container->getDefinition('twig.loader.filesystem')->getMethodCalls());
+ $twigLoader = $container->getDefinition('twig.loader.native_filesystem');
+ if ($container->has('templating')) {
+ $loader = $container->getDefinition('twig.loader.filesystem');
+ $loader->setMethodCalls(array_merge($twigLoader->getMethodCalls(), $loader->getMethodCalls()));
- $container->setDefinition('twig.loader.filesystem', $loader);
+ $twigLoader->clearTag('twig.loader');
+ } else {
+ $container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false));
}
if ($container->has('assets.packages')) {
$container->getDefinition('twig.extension.assets')->addTag('twig.extension');
}
- $container->addResource(new ClassExistenceResource(YamlParser::class));
- if (class_exists(YamlParser::class)) {
+ if ($container->hasDefinition('twig.extension.yaml')) {
$container->getDefinition('twig.extension.yaml')->addTag('twig.extension');
}
- $container->addResource(new ClassExistenceResource(Stopwatch::class));
- if (class_exists(Stopwatch::class)) {
+ if (class_exists('Symfony\Component\Stopwatch\Stopwatch')) {
$container->getDefinition('twig.extension.debug.stopwatch')->addTag('twig.extension');
}
- $container->addResource(new ClassExistenceResource(ExpressionLanguage::class));
- if (class_exists(ExpressionLanguage::class)) {
+ if ($container->hasDefinition('twig.extension.expression')) {
$container->getDefinition('twig.extension.expression')->addTag('twig.extension');
}
}
-
- private function getComposerRootDir($rootDir)
- {
- $dir = $rootDir;
- while (!file_exists($dir.'/composer.json')) {
- if ($dir === dirname($dir)) {
- return $rootDir;
- }
-
- $dir = dirname($dir);
- }
-
- return $dir;
- }
}
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php
index 6a4c1f269053c..a4defc51ff33a 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php
@@ -13,6 +13,8 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+use Symfony\Component\DependencyInjection\Reference;
/**
* Registers Twig runtime services.
@@ -27,20 +29,11 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition('twig.runtime_loader');
$mapping = array();
- foreach ($container->findTaggedServiceIds('twig.runtime') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('twig.runtime', true) as $id => $attributes) {
$def = $container->getDefinition($id);
-
- if (!$def->isPublic()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must be public as it can be lazy-loaded.', $id));
- }
-
- if ($def->isAbstract()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id));
- }
-
- $mapping[$def->getClass()] = $id;
+ $mapping[$def->getClass()] = new Reference($id);
}
- $definition->replaceArgument(1, $mapping);
+ $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $mapping));
}
}
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php
index 927e4b46e18ac..f520ab11f0096 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigEnvironmentPass.php
@@ -36,7 +36,7 @@ public function process(ContainerBuilder $container)
// be registered.
$calls = $definition->getMethodCalls();
$definition->setMethodCalls(array());
- foreach ($container->findTaggedServiceIds('twig.extension') as $id => $attributes) {
+ foreach ($container->findTaggedServiceIds('twig.extension', true) as $id => $attributes) {
$definition->addMethodCall('addExtension', array(new Reference($id)));
}
$definition->setMethodCalls(array_merge($definition->getMethodCalls(), $calls));
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php
index bc3b71c696ed7..f2c1d32eec974 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php
@@ -29,27 +29,23 @@ public function process(ContainerBuilder $container)
return;
}
- // register additional template loaders
- $loaderIds = $container->findTaggedServiceIds('twig.loader');
+ $prioritizedLoaders = array();
+ $found = 0;
- if (count($loaderIds) === 0) {
+ foreach ($container->findTaggedServiceIds('twig.loader', true) as $id => $attributes) {
+ $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
+ $prioritizedLoaders[$priority][] = $id;
+ ++$found;
+ }
+
+ if (!$found) {
throw new LogicException('No twig loaders found. You need to tag at least one loader with "twig.loader"');
}
- if (count($loaderIds) === 1) {
- $container->setAlias('twig.loader', key($loaderIds));
+ if (1 === $found) {
+ $container->setAlias('twig.loader', $id);
} else {
$chainLoader = $container->getDefinition('twig.loader.chain');
-
- $prioritizedLoaders = array();
-
- foreach ($loaderIds as $id => $tags) {
- foreach ($tags as $tag) {
- $priority = isset($tag['priority']) ? $tag['priority'] : 0;
- $prioritizedLoaders[$priority][] = $id;
- }
- }
-
krsort($prioritizedLoaders);
foreach ($prioritizedLoaders as $loaders) {
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
index 5296ac542ca87..8e37cbba871b8 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
@@ -11,12 +11,14 @@
namespace Symfony\Bundle\TwigBundle\DependencyInjection;
+use Symfony\Bridge\Twig\Extension\WebLinkExtension;
use Symfony\Component\Config\FileLocator;
-use Symfony\Component\Config\Resource\FileExistenceResource;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\Component\WebLink\HttpHeaderSerializer;
/**
* TwigExtension.
@@ -37,6 +39,24 @@ public function load(array $configs, ContainerBuilder $container)
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('twig.xml');
+ if (class_exists('Symfony\Component\Form\Form')) {
+ $loader->load('form.xml');
+ }
+
+ if (interface_exists('Symfony\Component\Templating\EngineInterface')) {
+ $loader->load('templating.xml');
+ }
+
+ if (!interface_exists('Symfony\Component\Translation\TranslatorInterface')) {
+ $container->removeDefinition('twig.translation.extractor');
+ }
+
+ if (class_exists(HttpHeaderSerializer::class)) {
+ $definition = $container->register('twig.extension.weblink', WebLinkExtension::class);
+ $definition->setPublic(false);
+ $definition->addArgument(new Reference('request_stack'));
+ }
+
foreach ($configs as $key => $config) {
if (isset($config['globals'])) {
foreach ($config['globals'] as $name => $value) {
@@ -66,7 +86,7 @@ public function load(array $configs, ContainerBuilder $container)
$envConfiguratorDefinition->replaceArgument(4, $config['number_format']['decimal_point']);
$envConfiguratorDefinition->replaceArgument(5, $config['number_format']['thousands_separator']);
- $twigFilesystemLoaderDefinition = $container->getDefinition('twig.loader.filesystem');
+ $twigFilesystemLoaderDefinition = $container->getDefinition('twig.loader.native_filesystem');
// register user-configured paths
foreach ($config['paths'] as $path => $namespace) {
@@ -80,27 +100,25 @@ public function load(array $configs, ContainerBuilder $container)
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']);
- // register bundles as Twig namespaces
- foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
- $dir = $container->getParameter('kernel.root_dir').'/Resources/'.$bundle.'/views';
- if (is_dir($dir)) {
- $this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle);
+ $bundleHierarchy = $this->getBundleHierarchy($container);
+
+ foreach ($bundleHierarchy as $name => $bundle) {
+ $namespace = $this->normalizeBundleName($name);
+
+ foreach ($bundle['children'] as $child) {
+ foreach ($bundleHierarchy[$child]['paths'] as $path) {
+ $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
+ }
}
- $container->addResource(new FileExistenceResource($dir));
- $reflection = new \ReflectionClass($class);
- $dir = dirname($reflection->getFileName()).'/Resources/views';
- if (is_dir($dir)) {
- $this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle);
+ foreach ($bundle['paths'] as $path) {
+ $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
}
- $container->addResource(new FileExistenceResource($dir));
}
- $dir = $container->getParameter('kernel.root_dir').'/Resources/views';
- if (is_dir($dir)) {
+ if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/views', false)) {
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir));
}
- $container->addResource(new FileExistenceResource($dir));
if (!empty($config['globals'])) {
$def = $container->getDefinition('twig');
@@ -126,25 +144,82 @@ public function load(array $configs, ContainerBuilder $container)
$container->getDefinition('twig')->replaceArgument(1, $config);
- $this->addClassesToCompile(array(
- 'Twig_Environment',
- 'Twig_Extension',
- 'Twig_Extension_Core',
- 'Twig_Extension_Escaper',
- 'Twig_Extension_Optimizer',
- 'Twig_LoaderInterface',
- 'Twig_Markup',
- 'Twig_Template',
- ));
+ $container->registerForAutoconfiguration(\Twig_ExtensionInterface::class)
+ ->addTag('twig.extension');
+ $container->registerForAutoconfiguration(\Twig_LoaderInterface::class)
+ ->addTag('twig.loader');
+
+ if (PHP_VERSION_ID < 70000) {
+ $this->addClassesToCompile(array(
+ 'Twig_Environment',
+ 'Twig_Extension',
+ 'Twig_Extension_Core',
+ 'Twig_Extension_Escaper',
+ 'Twig_Extension_Optimizer',
+ 'Twig_LoaderInterface',
+ 'Twig_Markup',
+ 'Twig_Template',
+ ));
+ }
+ }
+
+ private function getBundleHierarchy(ContainerBuilder $container)
+ {
+ $bundleHierarchy = array();
+
+ foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
+ if (!array_key_exists($name, $bundleHierarchy)) {
+ $bundleHierarchy[$name] = array(
+ 'paths' => array(),
+ 'parents' => array(),
+ 'children' => array(),
+ );
+ }
+
+ if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views', false)) {
+ $bundleHierarchy[$name]['paths'][] = $dir;
+ }
+
+ if ($container->fileExists($dir = $bundle['path'].'/Resources/views', false)) {
+ $bundleHierarchy[$name]['paths'][] = $dir;
+ }
+
+ if (null === $bundle['parent']) {
+ continue;
+ }
+
+ $bundleHierarchy[$name]['parents'][] = $bundle['parent'];
+
+ if (!array_key_exists($bundle['parent'], $bundleHierarchy)) {
+ $bundleHierarchy[$bundle['parent']] = array(
+ 'paths' => array(),
+ 'parents' => array(),
+ 'children' => array(),
+ );
+ }
+
+ $bundleHierarchy[$bundle['parent']]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$bundle['parent']]['children']);
+
+ foreach ($bundleHierarchy[$bundle['parent']]['parents'] as $parent) {
+ $bundleHierarchy[$name]['parents'][] = $parent;
+ $bundleHierarchy[$parent]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$parent]['children']);
+ }
+
+ foreach ($bundleHierarchy[$name]['children'] as $child) {
+ $bundleHierarchy[$child]['parents'] = array_merge($bundleHierarchy[$child]['parents'], $bundleHierarchy[$name]['parents']);
+ }
+ }
+
+ return $bundleHierarchy;
}
- private function addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle)
+ private function normalizeBundleName($name)
{
- $name = $bundle;
if ('Bundle' === substr($name, -6)) {
$name = substr($name, 0, -6);
}
- $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir, $name));
+
+ return $name;
}
/**
diff --git a/src/Symfony/Bundle/TwigBundle/LICENSE b/src/Symfony/Bundle/TwigBundle/LICENSE
index 12a74531e40a4..17d16a13367dd 100644
--- a/src/Symfony/Bundle/TwigBundle/LICENSE
+++ b/src/Symfony/Bundle/TwigBundle/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2016 Fabien Potencier
+Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
index 53fe300e29a62..0a9ac7a3ca19a 100644
--- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
+++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
@@ -29,12 +29,13 @@ class FilesystemLoader extends \Twig_Loader_Filesystem
/**
* Constructor.
*
- * @param FileLocatorInterface $locator A FileLocatorInterface instance
- * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance
+ * @param FileLocatorInterface $locator A FileLocatorInterface instance
+ * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance
+ * @param string|null $rootPath The root path common to all relative paths (null for getcwd())
*/
- public function __construct(FileLocatorInterface $locator, TemplateNameParserInterface $parser)
+ public function __construct(FileLocatorInterface $locator, TemplateNameParserInterface $parser, $rootPath = null)
{
- parent::__construct(array());
+ parent::__construct(array(), $rootPath);
$this->locator = $locator;
$this->parser = $parser;
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml
new file mode 100644
index 0000000000000..f1603c15461bd
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ twig.form.renderer
+
+
+
+
+ %twig.form.resources%
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/templating.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/templating.xml
new file mode 100644
index 0000000000000..b9c1806221ed0
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/templating.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+ %kernel.project_dir%
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
index c82cbafbeb953..22ad287f70113 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
@@ -17,6 +17,7 @@
+
%kernel.environment%
@@ -27,7 +28,8 @@
-
+
+
@@ -46,25 +48,12 @@
-
-
-
-
-
-
+ %kernel.project_dir%
-
-
-
-
-
-
-
-
@@ -87,7 +76,7 @@
-
+
%kernel.root_dir%
%kernel.charset%
@@ -117,21 +106,8 @@
-
-
-
- %twig.form.resources%
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
index c27cc56e6a078..25c84a6c9b5ec 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
@@ -1 +1 @@
-{% include '@Twig/Exception/error.xml.twig' %}
+{{ include('@Twig/Exception/error.xml.twig') }}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
index c27cc56e6a078..25c84a6c9b5ec 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
@@ -1 +1 @@
-{% include '@Twig/Exception/error.xml.twig' %}
+{{ include('@Twig/Exception/error.xml.twig') }}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
index d507ce46f6949..2cdf03f2bcb59 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
@@ -1 +1 @@
-{% include '@Twig/Exception/exception.xml.twig' with { 'exception': exception } %}
+{{ include('@Twig/Exception/exception.xml.twig', { exception: exception }) }}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
index bdf242b7f1998..593d490257e35 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
@@ -1,3 +1,3 @@
/*
-{% include '@Twig/Exception/exception.txt.twig' with { 'exception': exception } %}
+{{ include('@Twig/Exception/exception.txt.twig', { exception: exception }) }}
*/
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
index f405f6473e8f5..4b35e4fad77db 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
@@ -1,122 +1,99 @@
-
-
-
-
- {{ include('@Twig/Exception/exception.svg') }}
+