Upgrade 1-11.38

This commit is contained in:
xesmyd
2026-03-30 14:10:30 +02:00
parent f2a7e6d1fc
commit ac648ef29d
24665 changed files with 69682 additions and 2205004 deletions
+23
View File
@@ -1,6 +1,29 @@
CHANGELOG
=========
3.2.0
-----
* Removed `doctrine/annotations` from the list of required dependencies in `composer.json`
* Removed `symfony/security-core` and `symfony/security-csrf` from the list of required dependencies in `composer.json`
* Removed `symfony/templating` from the list of required dependencies in `composer.json`
* Removed `symfony/translation` from the list of required dependencies in `composer.json`
* 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`
3.1.0
-----
* Added `Controller::json` to simplify creating JSON responses when using the Serializer component
* Deprecated absolute template paths support in the template name parser
* Deprecated using core form types without dependencies as services
* Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()`
* Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector`
* The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been
deprecated. APCu should now be automatically used when available.
3.0.0
-----
@@ -21,6 +21,13 @@ use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
*/
class ClassCacheCacheWarmer implements CacheWarmerInterface
{
private $declaredClasses;
public function __construct(array $declaredClasses = null)
{
$this->declaredClasses = $declaredClasses;
}
/**
* Warms up the cache.
*
@@ -37,8 +44,9 @@ class ClassCacheCacheWarmer implements CacheWarmerInterface
if (file_exists($cacheDir.'/classes.php')) {
return;
}
$declared = null !== $this->declaredClasses ? $this->declaredClasses : array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits());
ClassCollectionLoader::load(include($classmap), $cacheDir, 'classes', false);
ClassCollectionLoader::inline(include($classmap), $cacheDir.'/classes.php', $declared);
}
/**
@@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
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;
/**
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;
use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator;
@@ -43,13 +44,16 @@ class TemplatePathsCacheWarmer extends CacheWarmer
*/
public function warmUp($cacheDir)
{
$filesystem = new Filesystem();
$templates = array();
foreach ($this->finder->findAllTemplates() as $template) {
$templates[$template->getLogicalName()] = $this->locator->locate($template);
$templates[$template->getLogicalName()] = rtrim($filesystem->makePathRelative($this->locator->locate($template), $cacheDir), '/');
}
$this->writeCacheFile($cacheDir.'/templates.php', sprintf('<?php return %s;', var_export($templates, true)));
$templates = str_replace("' => '", "' => __DIR__.'/", var_export($templates, true));
$this->writeCacheFile($cacheDir.'/templates.php', sprintf("<?php return %s;\n", $templates));
}
/**
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\Translation\TranslatorInterface;
@@ -22,11 +23,24 @@ use Symfony\Component\Translation\TranslatorInterface;
*/
class TranslationsCacheWarmer implements CacheWarmerInterface
{
private $container;
private $translator;
public function __construct(TranslatorInterface $translator)
/**
* TranslationsCacheWarmer constructor.
*
* @param ContainerInterface|TranslatorInterface $container
*/
public function __construct($container)
{
$this->translator = $translator;
// As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected.
if ($container instanceof ContainerInterface) {
$this->container = $container;
} elseif ($container instanceof TranslatorInterface) {
$this->translator = $container;
} else {
throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Symfony\Component\Translation\TranslatorInterface as first argument.', __CLASS__));
}
}
/**
@@ -34,6 +48,10 @@ class TranslationsCacheWarmer implements CacheWarmerInterface
*/
public function warmUp($cacheDir)
{
if (null === $this->translator) {
$this->translator = $this->container->get('translator');
}
if ($this->translator instanceof WarmableInterface) {
$this->translator->warmUp($cacheDir);
}
@@ -27,6 +27,7 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
{
protected function listBundles($output)
{
$title = 'Available registered bundles with their extension alias if available';
$headers = array('Bundle name', 'Extension alias');
$rows = array();
@@ -41,9 +42,10 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
}
if ($output instanceof StyleInterface) {
$output->title($title);
$output->table($headers, $rows);
} else {
$output->writeln('Available registered bundles with their extension alias if available:');
$output->writeln($title);
$table = new Table($output);
$table->setHeaders($headers)->setRows($rows)->render();
}
@@ -52,6 +54,8 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
protected function findExtension($name)
{
$bundles = $this->initializeBundles();
$minScore = INF;
foreach ($bundles as $bundle) {
if ($name === $bundle->getName()) {
if (!$bundle->getContainerExtension()) {
@@ -61,16 +65,37 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
return $bundle->getContainerExtension();
}
$distance = levenshtein($name, $bundle->getName());
if ($distance < $minScore) {
$guess = $bundle->getName();
$minScore = $distance;
}
$extension = $bundle->getContainerExtension();
if ($extension && $name === $extension->getAlias()) {
return $extension;
if ($extension) {
if ($name === $extension->getAlias()) {
return $extension;
}
$distance = levenshtein($name, $extension->getAlias());
if ($distance < $minScore) {
$guess = $extension->getAlias();
$minScore = $distance;
}
}
}
if ('Bundle' !== substr($name, -6)) {
$message = sprintf('No extensions with configuration available for "%s"', $name);
$message = sprintf('No extensions with configuration available for "%s".', $name);
} else {
$message = sprintf('No extension with alias "%s" is enabled', $name);
$message = sprintf('No extension with alias "%s" is enabled.', $name);
}
if (isset($guess) && $minScore < 3) {
$message .= sprintf("\n\nDid you mean \"%s\"?", $guess);
}
throw new \LogicException($message);
@@ -92,7 +117,7 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
// Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method
// as this method is not called when the container is loaded from the cache.
$container = $this->getContainerBuilder();
$bundles = $this->getContainer()->get('kernel')->registerBundles();
$bundles = $this->getContainer()->get('kernel')->getBundles();
foreach ($bundles as $bundle) {
if ($extension = $bundle->getContainerExtension()) {
$container->registerExtension($extension);
@@ -110,13 +110,16 @@ EOT
$rows = array();
$copyUsed = false;
$exitCode = 0;
$validAssetDirs = array();
/** @var BundleInterface $bundle */
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
if (!is_dir($originDir = $bundle->getPath().'/Resources/public')) {
continue;
}
$targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
$assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName()));
$targetDir = $bundlesDir.$assetDir;
$validAssetDirs[] = $assetDir;
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir);
@@ -149,6 +152,9 @@ EOT
$rows[] = array(sprintf('<fg=red;options=bold>%s</>', '\\' === DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage());
}
}
// remove the assets of the bundles that no longer exist
$dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir);
$this->filesystem->remove($dirsToRemove);
$io->table(array('', 'Bundle', 'Method / Error'), $rows);
+19 -26
View File
@@ -147,7 +147,7 @@ EOF
$safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel));
$realKernelFQN = get_class($realKernel);
foreach (Finder::create()->files()->name('*.meta')->in($warmupDir) as $file) {
foreach (Finder::create()->files()->depth('<3')->name('*.meta')->in($warmupDir) as $file) {
file_put_contents($file, preg_replace(
'/(C\:\d+\:)"'.$safeTempKernel.'"/',
sprintf('$1"%s"', $realKernelFQN),
@@ -159,26 +159,19 @@ EOF
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
$replace = str_replace('\\', '/', $realCacheDir);
foreach (Finder::create()->files()->in($warmupDir) as $file) {
$content = str_replace($search, $replace, file_get_contents($file));
file_put_contents($file, $content);
$content = str_replace($search, $replace, file_get_contents($file), $count);
if ($count) {
file_put_contents($file, $content);
}
}
// fix references to kernel/container related classes
$fileSearch = $tempKernel->getName().ucfirst($tempKernel->getEnvironment()).'*';
$search = array(
$tempKernel->getName().ucfirst($tempKernel->getEnvironment()),
sprintf('\'kernel.name\' => \'%s\'', $tempKernel->getName()),
sprintf('key="kernel.name">%s<', $tempKernel->getName()),
);
$replace = array(
$realKernel->getName().ucfirst($realKernel->getEnvironment()),
sprintf('\'kernel.name\' => \'%s\'', $realKernel->getName()),
sprintf('key="kernel.name">%s<', $realKernel->getName()),
);
foreach (Finder::create()->files()->name($fileSearch)->in($warmupDir) as $file) {
$content = str_replace($search, $replace, file_get_contents($file));
file_put_contents(str_replace($search, $replace, $file), $content);
unlink($file);
// fix references to container's class
$tempContainerClass = get_class($tempKernel->getContainer());
$realContainerClass = get_class($realKernel->getContainer());
foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) {
$content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file));
file_put_contents($file, $content);
rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file));
}
// remove temp kernel file after cache warmed up
@@ -201,8 +194,8 @@ EOF
// the temp kernel class name must have the same length than the real one
// to avoid the many problems in serialized resources files
$class = substr($parentClass, 0, -1).'_';
// the temp kernel name must be changed too
$name = var_export(substr($parent->getName(), 0, -1).'_', true);
// the temp container class must be changed too
$containerClass = var_export(substr(get_class($parent->getContainer()), 0, -1).'_', true);
$code = <<<EOF
<?php
@@ -215,11 +208,6 @@ namespace $namespace
return $cacheDir;
}
public function getName()
{
return $name;
}
public function getRootDir()
{
return $rootDir;
@@ -230,6 +218,11 @@ namespace $namespace
return $logDir;
}
protected function getContainerClass()
{
return $containerClass;
}
protected function buildContainer()
{
\$container = parent::buildContainer();
@@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Yaml\Yaml;
/**
@@ -34,9 +35,10 @@ class ConfigDebugCommand extends AbstractConfigCommand
->setName('debug:config')
->setDefinition(array(
new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'),
new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
))
->setDescription('Dumps the current configuration for an extension')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> command dumps the current configuration for an
extension/bundle.
@@ -45,6 +47,10 @@ Either the extension alias or bundle name can be used:
<info>php %command.full_name% framework</info>
<info>php %command.full_name% FrameworkBundle</info>
For dumping a specific option, add its path as second argument:
<info>php %command.full_name% framework serializer.enabled</info>
EOF
)
;
@@ -56,12 +62,11 @@ EOF
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name');
if (empty($name)) {
$io->comment('Provide the name of a bundle as the first argument of this command to dump its configuration.');
$io->newLine();
$this->listBundles($output);
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. <comment>debug:config FrameworkBundle</comment>)');
$io->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>debug:config FrameworkBundle serializer</comment> to dump the <comment>framework.serializer</comment> configuration)');
return;
}
@@ -69,23 +74,38 @@ EOF
$extension = $this->findExtension($name);
$container = $this->compileContainer();
$configs = $container->getExtensionConfig($extension->getAlias());
$extensionAlias = $extension->getAlias();
$configs = $container->getExtensionConfig($extensionAlias);
$configuration = $extension->getConfiguration($configs, $container);
$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 ($name === $extension->getAlias()) {
$io->title(sprintf('Current configuration for extension with alias "%s"', $name));
} else {
$io->title(sprintf('Current configuration for "%s"', $name));
if (null === $path = $input->getArgument('path')) {
$io->title(
sprintf('Current configuration for %s', ($name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name)))
);
$io->writeln(Yaml::dump(array($extensionAlias => $config), 10));
return;
}
$io->writeln(Yaml::dump(array($extension->getAlias() => $config), 10));
try {
$config = $this->getConfigForPath($config, $path, $extensionAlias);
} catch (LogicException $e) {
$io->error($e->getMessage());
return;
}
$io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path));
$io->writeln(Yaml::dump($config, 10));
}
private function compileContainer()
@@ -100,4 +120,28 @@ EOF
return $container;
}
/**
* Iterate over configuration until the last step of the given path.
*
* @param array $config A bundle configuration
*
* @throws LogicException If the configuration does not exist
*
* @return mixed
*/
private function getConfigForPath(array $config, $path, $alias)
{
$steps = explode('.', $path);
foreach ($steps as $step) {
if (!array_key_exists($step, $config)) {
throw new LogicException(sprintf('Unable to find configuration for "%s.%s"', $alias, $path));
}
$config = $config[$step];
}
return $config;
}
}
@@ -68,12 +68,10 @@ EOF
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name');
if (empty($name)) {
$io->comment('Provide the name of a bundle as the first argument of this command to dump its default configuration.');
$io->newLine();
$this->listBundles($output);
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. <comment>config:dump-reference FrameworkBundle</comment>)');
return;
}
@@ -19,6 +19,7 @@ use Symfony\Component\Console\Output\OutputInterface;
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;
/**
@@ -96,7 +97,11 @@ EOF
$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);
@@ -168,11 +173,11 @@ EOF
}
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();
@@ -194,7 +199,9 @@ EOF
throw new \InvalidArgumentException(sprintf('No services found that match "%s".', $name));
}
return $io->choice('Select one of the following services to display its information', $matchingServices);
$default = 1 === count($matchingServices) ? $matchingServices[0] : null;
return $io->choice('Select one of the following services to display its information', $matchingServices, $default);
}
private function findServiceIdsContaining(ContainerBuilder $builder, $name)
@@ -39,7 +39,7 @@ class EventDispatcherDebugCommand extends ContainerAwareCommand
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
))
->setDescription('Displays configured listeners for an application')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all configured listeners:
<info>php %command.full_name%</info>
@@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -78,10 +79,10 @@ EOF
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name');
$helper = new DescriptorHelper();
$routes = $this->getContainer()->get('router')->getRouteCollection();
if ($name) {
$route = $this->getContainer()->get('router')->getRouteCollection()->get($name);
if (!$route) {
if (!$route = $routes->get($name)) {
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
}
@@ -94,8 +95,6 @@ EOF
'output' => $io,
));
} else {
$routes = $this->getContainer()->get('router')->getRouteCollection();
foreach ($routes as $route) {
$this->convertController($route);
}
@@ -111,7 +110,7 @@ EOF
private function convertController(Route $route)
{
$nameParser = $this->getContainer()->get('controller_name_converter');
$nameParser = new ControllerNameParser($this->getApplication()->getKernel());
if ($route->hasDefault('_controller')) {
try {
$route->setDefault('_controller', $nameParser->build($route->getDefault('_controller')));
+3 -1
View File
@@ -54,7 +54,9 @@ abstract class ServerCommand extends ContainerAwareCommand
return true;
}
list($hostname, $port) = explode(':', $address);
$pos = strrpos($address, ':');
$hostname = substr($address, 0, $pos);
$port = substr($address, $pos + 1);
$fp = @fsockopen($hostname, $port, $errno, $errstr, 5);
@@ -15,9 +15,12 @@ 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.
@@ -113,14 +116,23 @@ EOF
$builder->setWorkingDirectory($documentRoot);
$builder->setTimeout(null);
$process = $builder->getProcess();
$callback = null;
if (OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) {
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);
};
}
}
$this
->getHelper('process')
->run($output, $process, null, null, OutputInterface::VERBOSITY_VERBOSE);
$process->run($callback);
if (!$process->isSuccessful()) {
$errorMessages = array('Built-in server terminated unexpectedly.');
@@ -41,7 +41,7 @@ class ServerStartCommand extends ServerCommand
))
->setName('server:start')
->setDescription('Starts PHP built-in web server in the background')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> runs PHP's built-in web server:
<info>php %command.full_name%</info>
@@ -32,7 +32,7 @@ class ServerStatusCommand extends ServerCommand
{
$this
->setDefinition(array(
new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
))
->setName('server:status')
@@ -36,7 +36,7 @@ class ServerStopCommand extends ServerCommand
))
->setName('server:stop')
->setDescription('Stops PHP\'s built-in web server that was started with the server:start command')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> stops PHP's built-in web server:
<info>php %command.full_name%</info>
@@ -21,6 +21,8 @@ use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\DataCollectorTranslator;
use Symfony\Component\Translation\LoggingTranslator;
/**
* Helps finding unused or missing translation messages in a given locale
@@ -50,7 +52,7 @@ class TranslationDebugCommand extends ContainerAwareCommand
new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'),
))
->setDescription('Displays translation messages information')
->setHelp(<<<EOF
->setHelp(<<<'EOF'
The <info>%command.name%</info> command helps finding unused or missing translation
messages and comparing them with the fallback ones by inspecting the
templates and translation files of a given bundle or the app folder.
@@ -84,6 +86,18 @@ EOF
;
}
/**
* {@inheritdoc}
*/
public function isEnabled()
{
if (!class_exists('Symfony\Component\Translation\Translator')) {
return false;
}
return parent::isEnabled();
}
/**
* {@inheritdoc}
*/
@@ -295,7 +309,7 @@ EOF
{
$fallbackCatalogues = array();
$translator = $this->getContainer()->get('translator');
if ($translator instanceof Translator) {
if ($translator instanceof Translator || $translator instanceof DataCollectorTranslator || $translator instanceof LoggingTranslator) {
foreach ($translator->getFallbackLocales() as $fallbackLocale) {
if ($fallbackLocale === $locale) {
continue;
@@ -39,11 +39,13 @@ class TranslationUpdateCommand extends ContainerAwareCommand
new InputArgument('locale', InputArgument::REQUIRED, 'The locale'),
new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'),
new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'),
new InputOption('no-prefix', null, InputOption::VALUE_NONE, 'If set, no prefix is added to the translations'),
new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'yml'),
new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'),
new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'),
new InputOption('no-backup', null, InputOption::VALUE_NONE, 'Should backup be disabled'),
new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'),
new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to update'),
))
->setDescription('Updates the translation file')
->setHelp(<<<'EOF'
@@ -65,6 +67,18 @@ EOF
;
}
/**
* {@inheritdoc}
*/
public function isEnabled()
{
if (!class_exists('Symfony\Component\Translation\Translator')) {
return false;
}
return parent::isEnabled();
}
/**
* {@inheritdoc}
*/
@@ -120,7 +134,7 @@ EOF
$extractedCatalogue = new MessageCatalogue($input->getArgument('locale'));
$io->comment('Parsing templates...');
$extractor = $this->getContainer()->get('translation.extractor');
$extractor->setPrefix($input->getOption('prefix'));
$extractor->setPrefix($input->getOption('no-prefix') ? '' : $input->getOption('prefix'));
foreach ($transPaths as $path) {
$path .= 'views';
if (is_dir($path)) {
@@ -139,6 +153,11 @@ EOF
}
}
if (null !== $domain = $input->getOption('domain')) {
$currentCatalogue = $this->filterCatalogue($currentCatalogue, $domain);
$extractedCatalogue = $this->filterCatalogue($extractedCatalogue, $domain);
}
// process catalogues
$operation = $input->getOption('clean')
? new TargetOperation($currentCatalogue, $extractedCatalogue)
@@ -160,11 +179,8 @@ EOF
foreach ($operation->getDomains() as $domain) {
$newKeys = array_keys($operation->getNewMessages($domain));
$allKeys = array_keys($operation->getMessages($domain));
$domainMessagesCount = count($newKeys) + count($allKeys);
$io->section(sprintf('Messages extracted for domain "<info>%s</info>" (%d messages)', $domain, $domainMessagesCount));
$io->listing(array_merge(
$list = array_merge(
array_diff($allKeys, $newKeys),
array_map(function ($id) {
return sprintf('<fg=green>%s</>', $id);
@@ -172,7 +188,12 @@ EOF
array_map(function ($id) {
return sprintf('<fg=red>%s</>', $id);
}, array_keys($operation->getObsoleteMessages($domain)))
));
);
$domainMessagesCount = count($list);
$io->section(sprintf('Messages extracted for domain "<info>%s</info>" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : ''));
$io->listing($list);
$extractedMessagesCount += $domainMessagesCount;
}
@@ -181,7 +202,7 @@ EOF
$io->comment('Xliff output version is <info>1.2</info>');
}
$resultMessage = sprintf('%d messages were successfully extracted', $extractedMessagesCount);
$resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was');
}
if ($input->getOption('no-backup') === true) {
@@ -213,4 +234,23 @@ EOF
$io->success($resultMessage.'.');
}
private function filterCatalogue(MessageCatalogue $catalogue, $domain)
{
$filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
if ($messages = $catalogue->all($domain)) {
$filteredCatalogue->add($messages, $domain);
}
foreach ($catalogue->getResources() as $resource) {
$filteredCatalogue->addResource($resource);
}
if ($metadata = $catalogue->getMetadata('', $domain)) {
foreach ($metadata as $k => $v) {
$filteredCatalogue->setMetadata($k, $v, $domain);
}
}
return $filteredCatalogue;
}
}
+41 -127
View File
@@ -13,153 +13,67 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
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\Finder\Finder;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand;
/**
* Validates YAML files syntax and outputs encountered errors.
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Robin Chalas <robin.chalas@gmail.com>
*/
class YamlLintCommand extends Command
{
private $command;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->setName('lint:yaml');
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
->setName('lint:yaml')
->setDescription('Lints a file and outputs encountered errors')
->addArgument('filename', null, 'A file or a directory or STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
->setHelp(<<<EOF
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
the first encountered syntax error.
->setDescription($this->command->getDescription())
->setDefinition($this->command->getDefinition())
->setHelp($this->command->getHelp().<<<'EOF'
You can validate the syntax of a file:
<info>php %command.full_name% filename</info>
Or of a whole directory:
<info>php %command.full_name% dirname</info>
<info>php %command.full_name% dirname --format=json</info>
Or all YAML files in a bundle:
Or find all files in a bundle:
<info>php %command.full_name% @AcmeDemoBundle</info>
You can also pass the YAML contents from STDIN:
<info>cat filename | php %command.full_name%</info>
EOF
)
;
);
}
/**
* {@inheritdoc}
*/
public function isEnabled()
{
return class_exists(BaseLintCommand::class) && parent::isEnabled();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$filename = $input->getArgument('filename');
if (!$filename) {
if (0 !== ftell(STDIN)) {
throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.');
}
$content = '';
while (!feof(STDIN)) {
$content .= fread(STDIN, 1024);
}
return $this->display($input, $output, $io, array($this->validate($content)));
}
if (0 !== strpos($filename, '@') && !is_readable($filename)) {
throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename));
}
$files = array();
if (is_file($filename)) {
$files = array($filename);
} elseif (is_dir($filename)) {
$files = Finder::create()->files()->in($filename)->name('*.yml');
} else {
$dir = $this->getApplication()->getKernel()->locateResource($filename);
$files = Finder::create()->files()->in($dir)->name('*.yml');
}
$filesInfo = array();
foreach ($files as $file) {
$filesInfo[] = $this->validate(file_get_contents($file), $file);
}
return $this->display($input, $output, $io, $filesInfo);
}
private function validate($content, $file = null)
{
$parser = new Parser();
try {
$parser->parse($content);
} catch (ParseException $e) {
return array('file' => $file, 'valid' => false, 'message' => $e->getMessage());
}
return array('file' => $file, 'valid' => true);
}
private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, $files)
{
switch ($input->getOption('format')) {
case 'txt':
return $this->displayTxt($output, $io, $files);
case 'json':
return $this->displayJson($io, $files);
default:
throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
}
}
private function displayTxt(OutputInterface $output, SymfonyStyle $io, $filesInfo)
{
$errors = 0;
foreach ($filesInfo as $info) {
if ($info['valid'] && $output->isVerbose()) {
$io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
} elseif (!$info['valid']) {
++$errors;
$io->text(sprintf('<error> ERROR </error> in %s', $info['file']));
$io->text(sprintf('<error> >> %s</error>', $info['message']));
}
}
if ($errors === 0) {
$io->success(sprintf('All %d YAML files contain valid syntax.', count($filesInfo)));
} else {
$io->warning(sprintf('%d YAML files have valid syntax and %d contain errors.', count($filesInfo) - $errors, $errors));
}
return min($errors, 1);
}
private function displayJson(OutputInterface $output, $filesInfo)
{
$errors = 0;
array_walk($filesInfo, function (&$v) use (&$errors) {
$v['file'] = (string) $v['file'];
if (!$v['valid']) {
++$errors;
}
});
$output->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT));
return min($errors, 1);
return $this->command->execute($input, $output);
}
}
+29 -3
View File
@@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Console;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -39,10 +40,10 @@ class Application extends BaseApplication
{
$this->kernel = $kernel;
parent::__construct('Symfony', Kernel::VERSION.' - '.$kernel->getName().'/'.$kernel->getEnvironment().($kernel->isDebug() ? '/debug' : ''));
parent::__construct('Symfony', Kernel::VERSION);
$this->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment()));
$this->getDefinition()->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.'));
$this->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The environment name', $kernel->getEnvironment()));
$this->getDefinition()->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode'));
}
/**
@@ -80,6 +81,16 @@ class Application extends BaseApplication
return parent::doRun($input, $output);
}
/**
* {@inheritdoc}
*/
public function find($name)
{
$this->registerCommands();
return parent::find($name);
}
/**
* {@inheritdoc}
*/
@@ -100,6 +111,21 @@ class Application extends BaseApplication
return parent::all($namespace);
}
/**
* {@inheritdoc}
*/
public function getLongVersion()
{
return parent::getLongVersion().sprintf(' (kernel: <comment>%s</>, env: <comment>%s</>, debug: <comment>%s</>)', $this->kernel->getName(), $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false');
}
public function add(Command $command)
{
$this->registerCommands();
return parent::add($command);
}
protected function registerCommands()
{
if ($this->commandsRegistered) {
@@ -57,7 +57,7 @@ abstract class Descriptor implements DescriptorInterface
$this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options);
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);
@@ -208,25 +208,17 @@ class JsonDescriptor extends Descriptor
'public' => $definition->isPublic(),
'synthetic' => $definition->isSynthetic(),
'lazy' => $definition->isLazy(),
'shared' => $definition->isShared(),
'abstract' => $definition->isAbstract(),
'autowire' => $definition->isAutowired(),
'autowiring_types' => array(),
'file' => $definition->getFile(),
);
if (method_exists($definition, 'isShared')) {
$data['shared'] = $definition->isShared();
foreach ($definition->getAutowiringTypes() 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;
}
}
$data['file'] = $definition->getFile();
if ($factory = $definition->getFactory()) {
if (is_array($factory)) {
if ($factory[0] instanceof Reference) {
@@ -242,13 +234,19 @@ class JsonDescriptor extends Descriptor
}
}
$calls = $definition->getMethodCalls();
if (count($calls) > 0) {
$data['calls'] = array();
foreach ($calls as $callData) {
$data['calls'][] = $callData[0];
}
}
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);
}
}
}
@@ -179,20 +179,13 @@ class MarkdownDescriptor extends Descriptor
."\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')
;
if (method_exists($definition, 'isShared')) {
$output .= "\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no');
}
$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.'`';
}
foreach ($definition->getAutowiringTypes() as $autowiringType) {
$output .= "\n".'- Autowiring Type: `'.$autowiringType.'`';
}
if ($definition->getFile()) {
@@ -214,6 +207,11 @@ class MarkdownDescriptor extends Descriptor
}
}
$calls = $definition->getMethodCalls();
foreach ($calls as $callData) {
$output .= "\n".'- Call: `'.$callData[0].'`';
}
if (!(isset($options['omit_tags']) && $options['omit_tags'])) {
foreach ($definition->getTags() as $tagName => $tagData) {
foreach ($tagData as $parameters) {
@@ -225,7 +223,7 @@ class MarkdownDescriptor extends Descriptor
}
}
$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);
}
/**
@@ -236,7 +234,7 @@ class MarkdownDescriptor extends Descriptor
$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);
$this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output);
}
/**
@@ -351,7 +349,7 @@ class MarkdownDescriptor extends Descriptor
*/
private function formatRouterConfig(array $array)
{
if (!count($array)) {
if (!$array) {
return 'NONE';
}
@@ -252,8 +252,7 @@ class TextDescriptor extends Descriptor
$tableRows[] = array('Service ID', isset($options['id']) ? $options['id'] : '-');
$tableRows[] = array('Class', $definition->getClass() ?: '-');
$tags = $definition->getTags();
if (count($tags)) {
if ($tags = $definition->getTags()) {
$tagInformation = '';
foreach ($tags as $tagName => $tagData) {
foreach ($tagData as $tagParameters) {
@@ -274,26 +273,24 @@ class TextDescriptor extends Descriptor
}
$tableRows[] = array('Tags', $tagInformation);
$calls = $definition->getMethodCalls();
if (count($calls) > 0) {
$callInformation = array();
foreach ($calls as $call) {
$callInformation[] = $call[0];
}
$tableRows[] = array('Calls', implode(', ', $callInformation));
}
$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);
}
$autowiringTypes = $definition->getAutowiringTypes();
$tableRows[] = array('Autowiring Types', $autowiringTypes ? implode(', ', $autowiringTypes) : '-');
if ($definition->getFile()) {
$tableRows[] = array('Required File', $definition->getFile() ? $definition->getFile() : '-');
@@ -187,7 +187,7 @@ class XmlDescriptor extends Descriptor
$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 +196,18 @@ class XmlDescriptor extends Descriptor
}
}
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'));
@@ -349,21 +351,22 @@ class XmlDescriptor extends Descriptor
$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('file', $definition->getFile());
if (!$omitTags) {
$tags = $definition->getTags();
$calls = $definition->getMethodCalls();
if (count($calls) > 0) {
$serviceXML->appendChild($callsXML = $dom->createElement('calls'));
foreach ($calls as $callData) {
$callsXML->appendChild($callXML = $dom->createElement('call'));
$callXML->setAttribute('method', $callData[0]);
}
}
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) {
+51 -2
View File
@@ -13,8 +13,11 @@ namespace Symfony\Bundle\FrameworkBundle\Controller;
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;
@@ -64,8 +67,10 @@ abstract class Controller implements ContainerAwareInterface
*/
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 = $this->container->get('request_stack')->getCurrentRequest()->duplicate($query, null, $path);
$subRequest = $request->duplicate($query, null, $path);
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
@@ -97,6 +102,46 @@ abstract class Controller implements ContainerAwareInterface
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.
*
@@ -146,7 +191,11 @@ abstract class Controller implements ContainerAwareInterface
protected function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
{
if (!$this->isGranted($attributes, $object)) {
throw $this->createAccessDeniedException($message);
$exception = $this->createAccessDeniedException($message);
$exception->setAttributes($attributes);
$exception->setSubject($object);
throw $exception;
}
}
@@ -46,11 +46,12 @@ class ControllerNameParser
*/
public function parse($controller)
{
$originalController = $controller;
if (3 !== count($parts = explode(':', $controller))) {
$parts = explode(':', $controller);
if (3 !== count($parts) || in_array('', $parts, true)) {
throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.', $controller));
}
$originalController = $controller;
list($bundle, $controller, $action) = $parts;
$controller = str_replace('/', '\\', $controller);
$bundles = array();
@@ -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);
@@ -11,9 +11,9 @@
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\Reference;
/**
* Registers the cache warmers.
@@ -22,6 +22,8 @@ use Symfony\Component\DependencyInjection\Reference;
*/
class AddCacheWarmerPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
/**
* {@inheritdoc}
*/
@@ -31,20 +33,12 @@ class AddCacheWarmerPass implements CompilerPassInterface
return;
}
$warmers = array();
foreach ($container->findTaggedServiceIds('kernel.cache_warmer') as $id => $attributes) {
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
$warmers[$priority][] = new Reference($id);
}
$warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container);
if (empty($warmers)) {
return;
}
// sort by priority and flatten
krsort($warmers);
$warmers = call_user_func_array('array_merge', $warmers);
$container->getDefinition('cache_warmer')->replaceArgument(0, $warmers);
}
}
@@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
* AddConsoleCommandPass.
@@ -24,25 +25,27 @@ class AddConsoleCommandPass implements CompilerPassInterface
public function process(ContainerBuilder $container)
{
$commandServices = $container->findTaggedServiceIds('console.command');
$serviceIds = array();
foreach ($commandServices as $id => $tags) {
$definition = $container->getDefinition($id);
if (!$definition->isPublic()) {
throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be public.', $id));
}
if ($definition->isAbstract()) {
throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must not be abstract.', $id));
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')) {
throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "Symfony\\Component\\Console\\Command\\Command".', $id));
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('console.command.'.strtolower(str_replace('\\', '_', $class)), $id);
$container->setAlias($serviceId = 'console.command.'.strtolower(str_replace('\\', '_', $class)), $id);
$serviceIds[] = $definition->isPublic() ? $id : $serviceId;
}
$container->setParameter('console.command.ids', array_keys($commandServices));
$container->setParameter('console.command.ids', $serviceIds);
}
}
@@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
class AddConstraintValidatorsPass implements CompilerPassInterface
{
@@ -28,7 +29,17 @@ class AddConstraintValidatorsPass implements CompilerPassInterface
$validators[$attributes[0]['alias']] = $id;
}
$validators[$container->getDefinition($id)->getClass()] = $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));
}
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);
@@ -12,8 +12,8 @@
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\DependencyInjection\Reference;
/**
* Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority.
@@ -23,23 +23,16 @@ use Symfony\Component\DependencyInjection\Reference;
*/
class ConfigCachePass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
public function process(ContainerBuilder $container)
{
$resourceCheckers = array();
foreach ($container->findTaggedServiceIds('config_cache.resource_checker') as $id => $tags) {
$priority = isset($tags[0]['priority']) ? $tags[0]['priority'] : 0;
$resourceCheckers[$priority][] = new Reference($id);
}
$resourceCheckers = $this->findAndSortTaggedServices('config_cache.resource_checker', $container);
if (empty($resourceCheckers)) {
return;
}
// sort by priority and flatten
krsort($resourceCheckers);
$resourceCheckers = call_user_func_array('array_merge', $resourceCheckers);
$container->getDefinition('config_cache_factory')->replaceArgument(0, $resourceCheckers);
}
}
@@ -11,8 +11,10 @@
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\InvalidArgumentException;
/**
* Adds all services with the tags "form.type" and "form.type_guesser" as
@@ -22,6 +24,8 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
*/
class FormPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('form.extension')) {
@@ -36,7 +40,7 @@ class FormPass implements CompilerPassInterface
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));
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form types are lazy-loaded.', $serviceId));
}
// Support type access by FQCN
@@ -47,16 +51,18 @@ class FormPass implements CompilerPassInterface
$typeExtensions = array();
foreach ($container->findTaggedServiceIds('form.type_extension') as $serviceId => $tag) {
foreach ($this->findAndSortTaggedServices('form.type_extension', $container) as $reference) {
$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));
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type extensions are lazy-loaded.', $serviceId));
}
$tag = $serviceDefinition->getTag('form.type_extension');
if (isset($tag[0]['extended_type'])) {
$extendedType = $tag[0]['extended_type'];
} else {
throw new \InvalidArgumentException(sprintf('Tagged form type extension must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.', $serviceId));
throw new InvalidArgumentException(sprintf('Tagged form type extension must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.', $serviceId));
}
$typeExtensions[$extendedType][] = $serviceId;
@@ -69,7 +75,7 @@ class FormPass implements CompilerPassInterface
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));
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type guessers are lazy-loaded.', $serviceId));
}
}
@@ -26,11 +26,6 @@ class LoggingTranslatorPass implements CompilerPassInterface
return;
}
// skip if the symfony/translation version is lower than 2.6
if (!interface_exists('Symfony\Component\Translation\TranslatorBagInterface')) {
return;
}
if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) {
$translatorAlias = $container->getAlias('translator');
$definition = $container->getDefinition((string) $translatorAlias);
@@ -14,6 +14,7 @@ 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\DependencyInjection\Exception\InvalidArgumentException;
/**
* Adds tagged data_collector services to profiler service.
@@ -38,7 +39,7 @@ class ProfilerPass implements CompilerPassInterface
if (isset($attributes[0]['template'])) {
if (!isset($attributes[0]['id'])) {
throw new \InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template', $id));
throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template', $id));
}
$template = array($attributes[0]['id'], $attributes[0]['template']);
}
@@ -12,8 +12,8 @@
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\DependencyInjection\Reference;
/**
* Adds extractors to the property_info service.
@@ -22,6 +22,8 @@ use Symfony\Component\DependencyInjection\Reference;
*/
class PropertyInfoPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
/**
* {@inheritdoc}
*/
@@ -31,46 +33,18 @@ class PropertyInfoPass implements CompilerPassInterface
return;
}
$definition = $container->getDefinition('property_info');
$listExtractors = $this->findAndSortTaggedServices('property_info.list_extractor', $container);
$container->getDefinition('property_info')->replaceArgument(0, $listExtractors);
$definition->replaceArgument(0, $listExtractors);
$typeExtractors = $this->findAndSortTaggedServices('property_info.type_extractor', $container);
$container->getDefinition('property_info')->replaceArgument(1, $typeExtractors);
$definition->replaceArgument(1, $typeExtractors);
$descriptionExtractors = $this->findAndSortTaggedServices('property_info.description_extractor', $container);
$container->getDefinition('property_info')->replaceArgument(2, $descriptionExtractors);
$definition->replaceArgument(2, $descriptionExtractors);
$accessExtractors = $this->findAndSortTaggedServices('property_info.access_extractor', $container);
$container->getDefinition('property_info')->replaceArgument(3, $accessExtractors);
}
/**
* Finds all services with the given tag name and order them by their priority.
*
* @param string $tagName
* @param ContainerBuilder $container
*
* @return array
*/
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
{
$services = $container->findTaggedServiceIds($tagName);
$sortedServices = array();
foreach ($services as $serviceId => $tags) {
foreach ($tags as $attributes) {
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
$sortedServices[$priority][] = new Reference($serviceId);
}
}
if (empty($sortedServices)) {
return array();
}
krsort($sortedServices);
// Flatten the array
return call_user_func_array('array_merge', $sortedServices);
$definition->replaceArgument(3, $accessExtractors);
}
}
@@ -11,9 +11,10 @@
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\Reference;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
/**
* Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
@@ -23,6 +24,8 @@ use Symfony\Component\DependencyInjection\Reference;
*/
class SerializerPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('serializer')) {
@@ -31,42 +34,17 @@ class SerializerPass implements CompilerPassInterface
// 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);
}
/**
* Finds all services with the given tag name and order them by their priority.
*
* @param string $tagName
* @param ContainerBuilder $container
*
* @return array
*
* @throws \RuntimeException
*/
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
{
$services = $container->findTaggedServiceIds($tagName);
if (empty($services)) {
throw new \RuntimeException(sprintf('You must tag at least one service as "%s" to use the Serializer service', $tagName));
}
$sortedServices = array();
foreach ($services as $serviceId => $tags) {
foreach ($tags as $attributes) {
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
$sortedServices[$priority][] = new Reference($serviceId);
}
}
krsort($sortedServices);
// Flatten the array
return call_user_func_array('array_merge', $sortedServices);
}
}
@@ -11,8 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundleEngineInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface;
class TemplatingPass implements CompilerPassInterface
{
@@ -22,6 +24,11 @@ class TemplatingPass implements CompilerPassInterface
return;
}
if ($container->hasAlias('templating')) {
$definition = $container->findDefinition('templating');
$definition->setAutowiringTypes(array(ComponentEngineInterface::class, FrameworkBundleEngineInterface::class));
}
if ($container->hasDefinition('templating.engine.php')) {
$helpers = array();
foreach ($container->findTaggedServiceIds('templating.helper') as $id => $attributes) {
@@ -14,6 +14,7 @@ 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\DependencyInjection\Exception\RuntimeException;
/**
* Adds tagged translation.extractor services to translation extractor.
@@ -30,7 +31,7 @@ class TranslationExtractorPass implements CompilerPassInterface
foreach ($container->findTaggedServiceIds('translation.extractor') 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));
throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
}
$definition->addMethodCall('addExtractor', array($attributes[0]['alias'], new Reference($id)));
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
use Doctrine\Common\Annotations\Annotation;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
@@ -103,6 +104,7 @@ class Configuration implements ConfigurationInterface
$this->addSsiSection($rootNode);
$this->addFragmentsSection($rootNode);
$this->addProfilerSection($rootNode);
$this->addWorkflowSection($rootNode);
$this->addRouterSection($rootNode);
$this->addSessionSection($rootNode);
$this->addRequestSection($rootNode);
@@ -114,6 +116,8 @@ class Configuration implements ConfigurationInterface
$this->addSerializerSection($rootNode);
$this->addPropertyAccessSection($rootNode);
$this->addPropertyInfoSection($rootNode);
$this->addCacheSection($rootNode);
$this->addPhpErrorsSection($rootNode);
return $treeBuilder;
}
@@ -204,7 +208,7 @@ class Configuration implements ConfigurationInterface
->booleanNode('only_master_requests')->defaultFalse()->end()
->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end()
->arrayNode('matcher')
->canBeUnset()
->canBeEnabled()
->performNoDeepMerging()
->fixXmlConfig('ip')
->children()
@@ -225,13 +229,137 @@ class Configuration implements ConfigurationInterface
;
}
private function addWorkflowSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->fixXmlConfig('workflow')
->children()
->arrayNode('workflows')
->useAttributeAsKey('name')
->prototype('array')
->fixXmlConfig('support')
->fixXmlConfig('place')
->fixXmlConfig('transition')
->children()
->enumNode('type')
->values(array('workflow', 'state_machine'))
->defaultValue('workflow')
->end()
->arrayNode('marking_store')
->fixXmlConfig('argument')
->children()
->enumNode('type')
->values(array('multiple_state', 'single_state'))
->end()
->arrayNode('arguments')
->beforeNormalization()
->ifString()
->then(function ($v) { return array($v); })
->end()
->requiresAtLeastOneElement()
->prototype('scalar')
->end()
->end()
->scalarNode('service')
->cannotBeEmpty()
->end()
->end()
->validate()
->ifTrue(function ($v) { return isset($v['type']) && isset($v['service']); })
->thenInvalid('"type" and "service" cannot be used together.')
->end()
->validate()
->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); })
->end()
->prototype('scalar')
->cannotBeEmpty()
->validate()
->ifTrue(function ($v) { return !class_exists($v); })
->thenInvalid('The supported class %s does not exist.')
->end()
->end()
->end()
->scalarNode('initial_place')->defaultNull()->end()
->arrayNode('places')
->isRequired()
->requiresAtLeastOneElement()
->prototype('scalar')
->cannotBeEmpty()
->end()
->end()
->arrayNode('transitions')
->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()
->arrayNode('from')
->beforeNormalization()
->ifString()
->then(function ($v) { return array($v); })
->end()
->requiresAtLeastOneElement()
->prototype('scalar')
->cannotBeEmpty()
->end()
->end()
->arrayNode('to')
->beforeNormalization()
->ifString()
->then(function ($v) { return array($v); })
->end()
->requiresAtLeastOneElement()
->prototype('scalar')
->cannotBeEmpty()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
;
}
private function addRouterSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('router')
->info('router configuration')
->canBeUnset()
->canBeEnabled()
->children()
->scalarNode('resource')->isRequired()->end()
->scalarNode('type')->end()
@@ -258,7 +386,7 @@ class Configuration implements ConfigurationInterface
->children()
->arrayNode('session')
->info('session configuration')
->canBeUnset()
->canBeEnabled()
->children()
->scalarNode('storage_id')->defaultValue('session.storage.native')->end()
->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end()
@@ -272,6 +400,7 @@ class Configuration implements ConfigurationInterface
->scalarNode('gc_divisor')->end()
->scalarNode('gc_probability')->defaultValue(1)->end()
->scalarNode('gc_maxlifetime')->end()
->booleanNode('use_strict_mode')->end()
->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end()
->integerNode('metadata_update_threshold')
->defaultValue('0')
@@ -289,7 +418,7 @@ class Configuration implements ConfigurationInterface
->children()
->arrayNode('request')
->info('request configuration')
->canBeUnset()
->canBeEnabled()
->fixXmlConfig('format')
->children()
->arrayNode('formats')
@@ -318,7 +447,11 @@ class Configuration implements ConfigurationInterface
->children()
->arrayNode('templating')
->info('templating configuration')
->canBeUnset()
->canBeEnabled()
->beforeNormalization()
->ifTrue(function ($v) { return false === $v || is_array($v) && false === $v['enabled']; })
->then(function () { return array('enabled' => false, 'engines' => false); })
->end()
->children()
->scalarNode('hinclude_default_template')->defaultNull()->end()
->scalarNode('cache')->end()
@@ -345,8 +478,9 @@ class Configuration implements ConfigurationInterface
->example(array('twig'))
->isRequired()
->requiresAtLeastOneElement()
->canBeUnset()
->beforeNormalization()
->ifTrue(function ($v) { return !is_array($v); })
->ifTrue(function ($v) { return !is_array($v) && false !== $v; })
->then(function ($v) { return array($v); })
->end()
->prototype('scalar')->end()
@@ -373,9 +507,10 @@ class Configuration implements ConfigurationInterface
->children()
->arrayNode('assets')
->info('assets configuration')
->canBeUnset()
->canBeEnabled()
->fixXmlConfig('base_url')
->children()
->scalarNode('version_strategy')->defaultNull()->end()
->scalarNode('version')->defaultNull()->end()
->scalarNode('version_format')->defaultValue('%%s?%%s')->end()
->scalarNode('base_path')->defaultValue('')->end()
@@ -388,6 +523,12 @@ class Configuration implements ConfigurationInterface
->prototype('scalar')->end()
->end()
->end()
->validate()
->ifTrue(function ($v) {
return isset($v['version_strategy']) && isset($v['version']);
})
->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".')
->end()
->fixXmlConfig('package')
->children()
->arrayNode('packages')
@@ -395,6 +536,7 @@ class Configuration implements ConfigurationInterface
->prototype('array')
->fixXmlConfig('base_url')
->children()
->scalarNode('version_strategy')->defaultNull()->end()
->scalarNode('version')
->beforeNormalization()
->ifTrue(function ($v) { return '' === $v; })
@@ -412,6 +554,12 @@ class Configuration implements ConfigurationInterface
->prototype('scalar')->end()
->end()
->end()
->validate()
->ifTrue(function ($v) {
return isset($v['version_strategy']) && isset($v['version']);
})
->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.')
->end()
->end()
->end()
->end()
@@ -478,9 +626,9 @@ class Configuration implements ConfigurationInterface
->children()
->arrayNode('annotations')
->info('annotation configuration')
->addDefaultsIfNotSet()
->{class_exists(Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
->scalarNode('cache')->defaultValue('file')->end()
->scalarNode('cache')->defaultValue('php_array')->end()
->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end()
->booleanNode('debug')->defaultValue($this->debug)->end()
->end()
@@ -533,4 +681,77 @@ class Configuration implements ConfigurationInterface
->end()
;
}
private function addCacheSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('cache')
->info('Cache configuration')
->addDefaultsIfNotSet()
->fixXmlConfig('pool')
->children()
->scalarNode('prefix_seed')
->info('Used to namespace cache keys when using several apps with the same shared backend')
->example('my-application-name')
->end()
->scalarNode('app')
->info('App related cache pools configuration')
->defaultValue('cache.adapter.filesystem')
->end()
->scalarNode('system')
->info('System related cache pools configuration')
->defaultValue('cache.adapter.system')
->end()
->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools')->end()
->scalarNode('default_doctrine_provider')->end()
->scalarNode('default_psr6_provider')->end()
->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()
->arrayNode('pools')
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('adapter')->defaultValue('cache.app')->end()
->booleanNode('public')->defaultFalse()->end()
->integerNode('default_lifetime')->end()
->scalarNode('provider')
->info('The service name to use as provider when the specified adapter needs one.')
->end()
->scalarNode('clearer')->end()
->end()
->end()
->validate()
->ifTrue(function ($v) { return isset($v['cache.app']) || isset($v['cache.system']); })
->thenInvalid('"cache.app" and "cache.system" are reserved names')
->end()
->end()
->end()
->end()
->end()
;
}
private function addPhpErrorsSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('php_errors')
->info('PHP errors handling configuration')
->addDefaultsIfNotSet()
->children()
->booleanNode('log')
->info('Use the app logger instead of the PHP logger for logging PHP errors.')
->defaultValue($this->debug)
->treatNullLike($this->debug)
->end()
->booleanNode('throw')
->info('Throw PHP errors as \ErrorException instances.')
->defaultValue($this->debug)
->treatNullLike($this->debug)
->end()
->end()
->end()
->end()
;
}
}
@@ -11,6 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
use Doctrine\Common\Annotations\Reader;
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
@@ -23,6 +28,14 @@ use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Finder\Finder;
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\Serializer\Encoder\CsvEncoder;
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\Workflow;
/**
* FrameworkExtension.
@@ -30,12 +43,14 @@ use Symfony\Component\Config\FileLocator;
* @author Fabien Potencier <fabien@symfony.com>
* @author Jeremy Mikola <jmikola@gmail.com>
* @author Kévin Dunglas <dunglas@gmail.com>
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*/
class FrameworkExtension extends Extension
{
private $formConfigEnabled = false;
private $translationConfigEnabled = false;
private $sessionConfigEnabled = false;
private $annotationsConfigEnabled = false;
/**
* @var string|null
@@ -52,23 +67,34 @@ class FrameworkExtension extends Extension
*/
public function load(array $configs, ContainerBuilder $container)
{
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader = new XmlFileLoader($container, new FileLocator(dirname(__DIR__).'/Resources/config'));
$loader->load('web.xml');
$loader->load('services.xml');
$loader->load('fragment_renderer.xml');
// 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.
$loader->load('translation.xml');
// Property access is used by both the Form and the Validator component
$loader->load('property_access.xml');
// Load Cache configuration first as it is used by other components
$loader->load('cache.xml');
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
$this->annotationsConfigEnabled = $this->isConfigEnabled($container, $config['annotations']);
// 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')) {
throw new LogicException('Form support cannot be enabled as the Translation component is not installed.');
}
$loader->load('translation.xml');
}
if (isset($config['secret'])) {
$container->setParameter('kernel.secret', $config['secret']);
}
@@ -78,16 +104,32 @@ class FrameworkExtension extends Extension
$container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
$container->setParameter('kernel.default_locale', $config['default_locale']);
if (!$container->hasParameter('debug.file_link_format')) {
if (!$container->hasParameter('templating.helper.code.file_link_format')) {
$links = array(
'textmate' => 'txmt://open?url=file://%%f&line=%%l',
'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?file=%%f&line=%%l',
);
$ide = $config['ide'];
$container->setParameter('templating.helper.code.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide));
}
$container->setParameter('debug.file_link_format', '%templating.helper.code.file_link_format%');
}
if (!empty($config['test'])) {
$loader->load('test.xml');
}
if (isset($config['session'])) {
if ($this->isConfigEnabled($container, $config['session'])) {
$this->sessionConfigEnabled = true;
$this->registerSessionConfiguration($config['session'], $container, $loader);
}
if (isset($config['request'])) {
if ($this->isConfigEnabled($container, $config['request'])) {
$this->registerRequestConfiguration($config['request'], $container, $loader);
}
@@ -103,12 +145,20 @@ class FrameworkExtension extends Extension
$this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader);
if (isset($config['assets'])) {
if ($this->isConfigEnabled($container, $config['assets'])) {
if (!class_exists('Symfony\Component\Asset\Package')) {
throw new LogicException('Asset support cannot be enabled as the Asset component is not installed.');
}
$this->registerAssetsConfiguration($config['assets'], $container, $loader);
}
if (isset($config['templating'])) {
$this->registerTemplatingConfiguration($config['templating'], $config['ide'], $container, $loader);
if ($this->isConfigEnabled($container, $config['templating'])) {
if (!class_exists('Symfony\Component\Templating\PhpEngine')) {
throw new LogicException('Templating support cannot be enabled as the Templating component is not installed.');
}
$this->registerTemplatingConfiguration($config['templating'], $container, $loader);
}
$this->registerValidationConfiguration($config['validation'], $container, $loader);
@@ -117,70 +167,70 @@ class FrameworkExtension extends Extension
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
$this->registerTranslatorConfiguration($config['translator'], $container);
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
$this->registerCacheConfiguration($config['cache'], $container);
$this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
$this->registerDebugConfiguration($config['php_errors'], $container, $loader);
if (isset($config['router'])) {
if ($this->isConfigEnabled($container, $config['router'])) {
$this->registerRouterConfiguration($config['router'], $container, $loader);
}
$this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
$this->registerPropertyAccessConfiguration($config['property_access'], $container);
if (isset($config['serializer'])) {
if ($this->isConfigEnabled($container, $config['serializer'])) {
$this->registerSerializerConfiguration($config['serializer'], $container, $loader);
}
if (isset($config['property_info'])) {
if ($this->isConfigEnabled($container, $config['property_info'])) {
$this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader);
}
$loader->load('debug_prod.xml');
$definition = $container->findDefinition('debug.debug_handlers_listener');
$this->addAnnotatedClassesToCompile(array(
'**Bundle\\Controller\\',
'**Bundle\\Entity\\',
if ($container->hasParameter('templating.helper.code.file_link_format')) {
$definition->replaceArgument(5, '%templating.helper.code.file_link_format%');
}
if ($container->getParameter('kernel.debug')) {
$definition->replaceArgument(2, E_ALL & ~(E_COMPILE_ERROR | E_PARSE | E_ERROR | E_CORE_ERROR | E_RECOVERABLE_ERROR));
$loader->load('debug.xml');
$definition = $container->findDefinition('http_kernel');
$definition->replaceArgument(1, new Reference('debug.controller_resolver'));
// 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');
} else {
$definition->replaceArgument(1, null);
}
// Added explicitly so that we don't rely on the class map being dumped to make it work
'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\\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',
));
}
@@ -308,7 +358,7 @@ class FrameworkExtension extends Extension
$container->setParameter('profiler.storage.dsn', $config['dsn']);
if (isset($config['matcher'])) {
if ($this->isConfigEnabled($container, $config['matcher'])) {
if (isset($config['matcher']['service'])) {
$container->setAlias('profiler.request_matcher', $config['matcher']['service']);
} elseif (isset($config['matcher']['ip']) || isset($config['matcher']['path']) || isset($config['matcher']['ips'])) {
@@ -334,6 +384,130 @@ class FrameworkExtension extends Extension
}
}
/**
* Loads the workflow configuration.
*
* @param array $workflows A workflow configuration array
* @param ContainerBuilder $container A ContainerBuilder instance
* @param XmlFileLoader $loader An XmlFileLoader instance
*/
private function registerWorkflowConfiguration(array $workflows, ContainerBuilder $container, XmlFileLoader $loader)
{
if (!$workflows) {
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) {
$type = $workflow['type'];
$transitions = array();
foreach ($workflow['transitions'] as $transition) {
if ($type === 'workflow') {
$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($transition['name'], $from, $to));
}
}
}
}
// Create a Definition
$definitionDefinition = new Definition(Workflow\Definition::class);
$definitionDefinition->setPublic(false);
$definitionDefinition->addArgument($workflow['places']);
$definitionDefinition->addArgument($transitions);
$definitionDefinition->addTag('workflow.definition', array(
'name' => $name,
'type' => $type,
'marking_store' => isset($workflow['marking_store']['type']) ? $workflow['marking_store']['type'] : null,
));
if (isset($workflow['initial_place'])) {
$definitionDefinition->addArgument($workflow['initial_place']);
}
// Create MarkingStore
if (isset($workflow['marking_store']['type'])) {
$markingStoreDefinition = new DefinitionDecorator('workflow.marking_store.'.$workflow['marking_store']['type']);
foreach ($workflow['marking_store']['arguments'] as $argument) {
$markingStoreDefinition->addArgument($argument);
}
} elseif (isset($workflow['marking_store']['service'])) {
$markingStoreDefinition = new Reference($workflow['marking_store']['service']);
}
// Create Workflow
$workflowDefinition = new DefinitionDecorator(sprintf('%s.abstract', $type));
$workflowDefinition->replaceArgument(0, $definitionDefinition);
if (isset($markingStoreDefinition)) {
$workflowDefinition->replaceArgument(1, $markingStoreDefinition);
}
$workflowDefinition->replaceArgument(3, $name);
// Store to container
$workflowId = sprintf('%s.%s', $type, $name);
$container->setDefinition($workflowId, $workflowDefinition);
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
// Add workflow to Registry
foreach ($workflow['supports'] as $supportedClass) {
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $supportedClass));
}
}
}
/**
* Loads the debug configuration.
*
* @param array $config A php errors configuration array
* @param ContainerBuilder $container A ContainerBuilder instance
* @param XmlFileLoader $loader An XmlFileLoader instance
*/
private function registerDebugConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
$loader->load('debug_prod.xml');
$debug = $container->getParameter('kernel.debug');
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');
if (!$config['log']) {
$definition->replaceArgument(1, null);
}
if (!$config['throw']) {
$container->setParameter('debug.error_handler.throw_at', 0);
}
$definition->replaceArgument(4, $debug);
$definition->replaceArgument(6, $debug);
if ($debug && class_exists(DebugProcessor::class)) {
$definition = new Definition(DebugProcessor::class);
$definition->setPublic(false);
$container->setDefinition('debug.log_processor', $definition);
}
}
/**
* Loads the router configuration.
*
@@ -346,7 +520,7 @@ class FrameworkExtension extends Extension
$loader->load('routing.xml');
$container->setParameter('router.resource', $config['resource']);
$container->setParameter('router.cache_class_prefix', $container->getParameter('kernel.name').ucfirst($container->getParameter('kernel.environment')));
$container->setParameter('router.cache_class_prefix', $container->getParameter('kernel.container_class'));
$router = $container->findDefinition('router.default');
$argument = $router->getArgument(2);
$argument['strict_requirements'] = $config['strict_requirements'];
@@ -381,7 +555,7 @@ class FrameworkExtension extends Extension
// session storage
$container->setAlias('session.storage', $config['storage_id']);
$options = array();
foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode') as $key) {
if (isset($config[$key])) {
$options[$key] = $config[$key];
}
@@ -448,25 +622,13 @@ class FrameworkExtension extends Extension
* Loads the templating configuration.
*
* @param array $config A templating configuration array
* @param string $ide
* @param ContainerBuilder $container A ContainerBuilder instance
* @param XmlFileLoader $loader An XmlFileLoader instance
*/
private function registerTemplatingConfiguration(array $config, $ide, ContainerBuilder $container, XmlFileLoader $loader)
private function registerTemplatingConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
$loader->load('templating.xml');
if (!$container->hasParameter('templating.helper.code.file_link_format')) {
$links = array(
'textmate' => 'txmt://open?url=file://%%f&line=%%l',
'macvim' => 'mvim://open?url=file://%%f&line=%%l',
'emacs' => 'emacs://open?url=file://%%f&line=%%l',
'sublime' => 'subl://open?url=file://%%f&line=%%l',
);
$container->setParameter('templating.helper.code.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide));
}
$container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']);
if ($container->getParameter('kernel.debug')) {
@@ -565,14 +727,22 @@ class FrameworkExtension extends Extension
{
$loader->load('assets.xml');
$defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], '_default');
$defaultVersion = null;
if ($config['version_strategy']) {
$defaultVersion = new Reference($config['version_strategy']);
} else {
$defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], '_default');
}
$defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion);
$container->setDefinition('assets._default_package', $defaultPackage);
$namedPackages = array();
foreach ($config['packages'] as $name => $package) {
if (!array_key_exists('version', $package)) {
if (null !== $package['version_strategy']) {
$version = new Reference($package['version_strategy']);
} elseif (!array_key_exists('version', $package)) {
$version = $defaultVersion;
} else {
$format = $package['version_format'] ?: $config['version_format'];
@@ -598,23 +768,14 @@ class FrameworkExtension extends Extension
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 DefinitionDecorator($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)
@@ -644,6 +805,11 @@ class FrameworkExtension extends Extension
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;
// Use the "real" translator instead of the identity default
@@ -668,15 +834,14 @@ class FrameworkExtension extends Extension
if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) {
$r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException');
$dirs[] = dirname($r->getFileName()).'/../Resources/translations';
$dirs[] = dirname(dirname($r->getFileName())).'/Resources/translations';
}
$rootDir = $container->getParameter('kernel.root_dir');
foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
$reflection = new \ReflectionClass($class);
if (is_dir($dir = dirname($reflection->getFileName()).'/Resources/translations')) {
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
if (is_dir($dir = $bundle['path'].'/Resources/translations')) {
$dirs[] = $dir;
}
if (is_dir($dir = $rootDir.sprintf('/Resources/%s/translations', $bundle))) {
if (is_dir($dir = $rootDir.sprintf('/Resources/%s/translations', $name))) {
$dirs[] = $dir;
}
}
@@ -739,6 +904,10 @@ class FrameworkExtension extends Extension
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');
@@ -758,6 +927,10 @@ class FrameworkExtension extends Extension
$definition->replaceArgument(0, $config['strict_email']);
if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) {
if (!$this->annotationsConfigEnabled) {
throw new \LogicException('"enable_annotations" on the validator cannot be set as Annotations support is disabled.');
}
$validatorBuilder->addMethodCall('enableAnnotationMapping', array(new Reference('annotation_reader')));
}
@@ -767,13 +940,17 @@ class FrameworkExtension extends Extension
}
}
if (isset($config['cache'])) {
if (isset($config['cache']) && $config['cache']) {
@trigger_error('The "framework.validation.cache" option is deprecated since Symfony 3.2 and will be removed in 4.0. Configure the "cache.validator" service under "framework.cache.pools" instead.', E_USER_DEPRECATED);
$container->setParameter(
'validator.mapping.cache.prefix',
'validator_'.$this->getKernelRootHash($container)
);
$validatorBuilder->addMethodCall('setMetadataCache', array(new Reference($config['cache'])));
} elseif (!$container->getParameter('kernel.debug')) {
$validatorBuilder->addMethodCall('setMetadataCache', array(new Reference('validator.mapping.cache.symfony')));
}
}
@@ -787,27 +964,24 @@ class FrameworkExtension extends Extension
$container->addResource(new FileResource($files[0][0]));
}
$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][] = realpath($file);
$files[0][] = $file;
$container->addResource(new FileResource($file));
}
if (is_file($file = $dirname.'/Resources/config/validation.yml')) {
$files[1][] = realpath($file);
$files[1][] = $file;
$container->addResource(new FileResource($file));
}
if (is_dir($dir = $dirname.'/Resources/config/validation')) {
foreach (Finder::create()->files()->in($dir)->name('*.xml') as $file) {
$files[0][] = $file->getRealPath();
$files[0][] = $file->getPathname();
}
foreach (Finder::create()->files()->in($dir)->name('*.yml') as $file) {
$files[1][] = $file->getRealPath();
$files[1][] = $file->getPathname();
}
$container->addResource(new DirectoryResource($dir));
@@ -819,11 +993,33 @@ class FrameworkExtension extends Extension
private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, $loader)
{
if (!$this->annotationsConfigEnabled) {
return;
}
if (!class_exists('Doctrine\Common\Annotations\Annotation')) {
throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed.');
}
$loader->load('annotations.xml');
if ('none' !== $config['cache']) {
if ('file' === $config['cache']) {
$cacheService = $config['cache'];
if ('php_array' === $config['cache']) {
$cacheService = 'annotations.cache';
// Enable warmer only if PHP array is used for cache
$definition = $container->findDefinition('annotations.cache_warmer');
$definition->addTag('kernel.cache_warmer');
$this->addClassesToCompile(array(
'Symfony\Component\Cache\Adapter\PhpArrayAdapter',
'Symfony\Component\Cache\DoctrineProvider',
));
} elseif ('file' === $config['cache']) {
$cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir));
}
@@ -832,14 +1028,19 @@ class FrameworkExtension extends Extension
->getDefinition('annotations.filesystem_cache')
->replaceArgument(0, $cacheDir)
;
$cacheService = 'annotations.filesystem_cache';
}
$container
->getDefinition('annotations.cached_reader')
->replaceArgument(1, new Reference('file' !== $config['cache'] ? $config['cache'] : 'annotations.filesystem_cache'))
->replaceArgument(2, $config['debug'])
->addTag('annotations.cached_reader', array('provider' => $cacheService))
->addAutowiringType(Reader::class)
;
$container->setAlias('annotation_reader', 'annotations.cached_reader');
} else {
$container->removeDefinition('annotations.cached_reader');
}
}
@@ -867,6 +1068,10 @@ class FrameworkExtension extends Extension
return;
}
if (!class_exists('Symfony\Component\Security\Csrf\CsrfToken')) {
throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed.');
}
if (!$this->sessionConfigEnabled) {
throw new \LogicException('CSRF protection needs sessions to be enabled.');
}
@@ -884,8 +1089,37 @@ class FrameworkExtension extends Extension
*/
private function registerSerializerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
if (!$config['enabled']) {
return;
if (class_exists('Symfony\Component\Serializer\Normalizer\DataUriNormalizer')) {
// Run after serializer.normalizer.object
$definition = $container->register('serializer.normalizer.data_uri', DataUriNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -920));
}
if (class_exists('Symfony\Component\Serializer\Normalizer\DateTimeNormalizer')) {
// Run before serializer.normalizer.object
$definition = $container->register('serializer.normalizer.datetime', DateTimeNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -910));
}
if (class_exists('Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer')) {
// Run before serializer.normalizer.object
$definition = $container->register('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -900));
}
if (class_exists(YamlEncoder::class) && defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) {
$definition = $container->register('serializer.encoder.yaml', YamlEncoder::class);
$definition->setPublic(false);
$definition->addTag('serializer.encoder');
}
if (class_exists(CsvEncoder::class)) {
$definition = $container->register('serializer.encoder.csv', CsvEncoder::class);
$definition->setPublic(false);
$definition->addTag('serializer.encoder');
}
$loader->load('serializer.xml');
@@ -893,6 +1127,10 @@ class FrameworkExtension extends Extension
$serializerLoaders = array();
if (isset($config['enable_annotations']) && $config['enable_annotations']) {
if (!$this->annotationsConfigEnabled) {
throw new \LogicException('"enable_annotations" on the serializer cannot be set as Annotations support is disabled.');
}
$annotationLoader = new Definition(
'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader',
array(new Reference('annotation_reader'))
@@ -902,13 +1140,11 @@ class FrameworkExtension extends Extension
$serializerLoaders[] = $annotationLoader;
}
$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/serialization.xml')) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array(realpath($file)));
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file));
$definition->setPublic(false);
$serializerLoaders[] = $definition;
@@ -916,7 +1152,7 @@ class FrameworkExtension extends Extension
}
if (is_file($file = $dirname.'/Resources/config/serialization.yml')) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array(realpath($file)));
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file));
$definition->setPublic(false);
$serializerLoaders[] = $definition;
@@ -925,13 +1161,13 @@ class FrameworkExtension extends Extension
if (is_dir($dir = $dirname.'/Resources/config/serialization')) {
foreach (Finder::create()->files()->in($dir)->name('*.xml') as $file) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getRealPath()));
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getPathname()));
$definition->setPublic(false);
$serializerLoaders[] = $definition;
}
foreach (Finder::create()->files()->in($dir)->name('*.yml') as $file) {
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file->getRealPath()));
$definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file->getPathname()));
$definition->setPublic(false);
$serializerLoaders[] = $definition;
@@ -942,8 +1178,11 @@ class FrameworkExtension extends Extension
}
$chainLoader->replaceArgument(0, $serializerLoaders);
$container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders);
if (isset($config['cache']) && $config['cache']) {
@trigger_error('The "framework.serializer.cache" option is deprecated since Symfony 3.1 and will be removed in 4.0. Configure the "cache.serializer" service under "framework.cache.pools" instead.', E_USER_DEPRECATED);
$container->setParameter(
'serializer.mapping.cache.prefix',
'serializer_'.$this->getKernelRootHash($container)
@@ -952,6 +1191,18 @@ class FrameworkExtension extends Extension
$container->getDefinition('serializer.mapping.class_metadata_factory')->replaceArgument(
1, new Reference($config['cache'])
);
} elseif (!$container->getParameter('kernel.debug') && class_exists(CacheClassMetadataFactory::class)) {
$cacheMetadataFactory = new Definition(
CacheClassMetadataFactory::class,
array(
new Reference('serializer.mapping.cache_class_metadata_factory.inner'),
new Reference('serializer.mapping.cache.symfony'),
)
);
$cacheMetadataFactory->setPublic(false);
$cacheMetadataFactory->setDecoratedService('serializer.mapping.class_metadata_factory');
$container->setDefinition('serializer.mapping.cache_class_metadata_factory', $cacheMetadataFactory);
}
if (isset($config['name_converter']) && $config['name_converter']) {
@@ -968,19 +1219,67 @@ class FrameworkExtension extends Extension
*/
private function registerPropertyInfoConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
if (!$config['enabled']) {
return;
}
$loader->load('property_info.xml');
if (class_exists('phpDocumentor\Reflection\ClassReflector')) {
if (interface_exists('phpDocumentor\Reflection\DocBlockFactoryInterface')) {
$definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor');
$definition->addTag('property_info.description_extractor', array('priority' => -1000));
$definition->addTag('property_info.type_extractor', array('priority' => -1001));
}
}
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.adapter.apcu')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.system')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']);
if (isset($config['prefix_seed'])) {
$container->setParameter('cache.prefix.seed', $config['prefix_seed']);
}
foreach (array('doctrine', 'psr6', 'redis') as $name) {
if (isset($config[$name = 'default_'.$name.'_provider'])) {
$container->setAlias('cache.'.$name, new Alias(Compiler\CachePoolPass::getServiceProvider($container, $config[$name]), false));
}
}
foreach (array('app', 'system') as $name) {
$config['pools']['cache.'.$name] = array(
'adapter' => $config[$name],
'public' => true,
);
}
foreach ($config['pools'] as $name => $pool) {
$definition = new DefinitionDecorator($pool['adapter']);
$definition->setPublic($pool['public']);
unset($pool['adapter'], $pool['public']);
$definition->addTag('cache.pool', $pool);
$container->setDefinition($name, $definition);
}
if (method_exists(PropertyAccessor::class, 'createCache')) {
$propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class);
$propertyAccessDefinition->setPublic(false);
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',
));
}
/**
* Gets a hash of the kernel root directory.
*
@@ -1004,7 +1303,7 @@ class FrameworkExtension extends Extension
*/
public function getXsdValidationBasePath()
{
return __DIR__.'/../Resources/config/schema';
return dirname(__DIR__).'/Resources/config/schema';
}
public function getNamespace()
+15 -1
View File
@@ -11,11 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
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\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;
@@ -31,6 +37,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumpe
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\Debug\ErrorHandler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@@ -73,7 +80,8 @@ class FrameworkBundle extends Bundle
// 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());
$container->addCompilerPass(new AddConstraintValidatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new AddValidatorInitializersPass());
$container->addCompilerPass(new AddConsoleCommandPass());
$container->addCompilerPass(new FormPass());
@@ -87,8 +95,14 @@ class FrameworkBundle extends Bundle
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SerializerPass());
$container->addCompilerPass(new PropertyInfoPass());
$container->addCompilerPass(new DataCollectorTranslatorPass());
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
$container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32);
$container->addCompilerPass(new ValidateWorkflowsPass());
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
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);
+1 -1
View File
@@ -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
@@ -5,11 +5,15 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="annotations.reader" class="Doctrine\Common\Annotations\AnnotationReader" public="false" />
<service id="annotations.reader" class="Doctrine\Common\Annotations\AnnotationReader" public="false">
<autowiring-type>Doctrine\Common\Annotations\Reader</autowiring-type>
</service>
<service id="annotations.cached_reader" class="Doctrine\Common\Annotations\CachedReader" public="false">
<argument type="service" id="annotations.reader" />
<argument /><!-- Cache Implementation -->
<argument type="service">
<service class="Doctrine\Common\Cache\ArrayCache" />
</argument>
<argument /><!-- Debug-Flag -->
</service>
@@ -17,6 +21,22 @@
<argument /><!-- Cache-Directory -->
</service>
<service id="annotations.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" public="false">
<argument type="service" id="annotations.reader" />
<argument>%kernel.cache_dir%/annotations.php</argument>
<argument type="service" id="cache.annotations" />
</service>
<service id="annotations.cache" class="Symfony\Component\Cache\DoctrineProvider" public="false">
<argument type="service">
<service class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
<factory class="Symfony\Component\Cache\Adapter\PhpArrayAdapter" method="create" />
<argument>%kernel.cache_dir%/annotations.php</argument>
<argument type="service" id="cache.annotations" />
</service>
</argument>
</service>
<service id="annotation_reader" alias="annotations.reader" />
</services>
</container>
@@ -21,13 +21,13 @@
<service id="assets.path_package" class="Symfony\Component\Asset\PathPackage" abstract="true">
<argument /> <!-- base path -->
<argument type="service" /> <!-- version strategy -->
<argument /> <!-- version strategy -->
<argument type="service" id="assets.context" />
</service>
<service id="assets.url_package" class="Symfony\Component\Asset\UrlPackage" abstract="true">
<argument /> <!-- base URLs -->
<argument type="service" /> <!-- version strategy -->
<argument /> <!-- version strategy -->
<argument type="service" id="assets.context" />
</service>
@@ -10,7 +10,7 @@
<call method="setKernel"><argument type="service" id="kernel" on-invalid="ignore" /></call>
</service>
<service id="data_collector.request" class="Symfony\Component\HttpKernel\DataCollector\RequestDataCollector">
<service id="data_collector.request" class="Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector">
<tag name="kernel.event_subscriber" />
<tag name="data_collector" template="@WebProfiler/Collector/request.html.twig" id="request" priority="335" />
</service>
+8 -3
View File
@@ -6,7 +6,6 @@
<parameters>
<parameter key="debug.container.dump">%kernel.cache_dir%/%kernel.container_class%.xml</parameter>
<parameter key="debug.error_handler.throw_at">-1</parameter>
</parameters>
<services>
@@ -17,8 +16,14 @@
<argument type="service" id="logger" on-invalid="null" />
</service>
<service id="debug.controller_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableControllerResolver">
<argument type="service" id="controller_resolver" />
<service id="debug.controller_resolver" decorates="controller_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableControllerResolver">
<argument type="service" id="debug.controller_resolver.inner" />
<argument type="service" id="debug.stopwatch" />
<argument type="service" id="argument_resolver" />
</service>
<service id="debug.argument_resolver" decorates="argument_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver">
<argument type="service" id="debug.argument_resolver.inner" />
<argument type="service" id="debug.stopwatch" />
</service>
</services>
@@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="debug.error_handler.throw_at">0</parameter>
<parameter key="debug.error_handler.throw_at">-1</parameter>
</parameters>
<services>
@@ -14,12 +14,17 @@
<tag name="monolog.logger" channel="php" />
<argument>null</argument><!-- Exception handler -->
<argument type="service" id="logger" on-invalid="null" />
<argument>null</argument><!-- Log levels map for enabled error levels -->
<argument>null</argument>
<argument>-1</argument><!-- Log levels map for enabled error levels -->
<argument>%debug.error_handler.throw_at%</argument>
<argument>true</argument>
<argument type="service" id="debug.file_link_formatter"></argument>
<argument>true</argument>
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
</service>
<service id="debug.stopwatch" class="Symfony\Component\Stopwatch\Stopwatch" />
<service id="debug.file_link_formatter" class="Symfony\Component\HttpKernel\Debug\FileLinkFormatter" public="false">
<argument>%debug.file_link_format%</argument>
</service>
</services>
</container>
+29 -29
View File
@@ -66,95 +66,95 @@
<tag name="form.type" />
</service>
<service id="form.type.birthday" class="Symfony\Component\Form\Extension\Core\Type\BirthdayType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.checkbox" class="Symfony\Component\Form\Extension\Core\Type\CheckboxType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.choice" class="Symfony\Component\Form\Extension\Core\Type\ChoiceType">
<tag name="form.type" />
<argument type="service" id="form.choice_list_factory"/>
</service>
<service id="form.type.collection" class="Symfony\Component\Form\Extension\Core\Type\CollectionType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.country" class="Symfony\Component\Form\Extension\Core\Type\CountryType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.date" class="Symfony\Component\Form\Extension\Core\Type\DateType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.datetime" class="Symfony\Component\Form\Extension\Core\Type\DateTimeType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.email" class="Symfony\Component\Form\Extension\Core\Type\EmailType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.file" class="Symfony\Component\Form\Extension\Core\Type\FileType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.hidden" class="Symfony\Component\Form\Extension\Core\Type\HiddenType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.integer" class="Symfony\Component\Form\Extension\Core\Type\IntegerType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.language" class="Symfony\Component\Form\Extension\Core\Type\LanguageType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.locale" class="Symfony\Component\Form\Extension\Core\Type\LocaleType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.money" class="Symfony\Component\Form\Extension\Core\Type\MoneyType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.number" class="Symfony\Component\Form\Extension\Core\Type\NumberType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.password" class="Symfony\Component\Form\Extension\Core\Type\PasswordType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.percent" class="Symfony\Component\Form\Extension\Core\Type\PercentType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.radio" class="Symfony\Component\Form\Extension\Core\Type\RadioType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.range" class="Symfony\Component\Form\Extension\Core\Type\RangeType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.repeated" class="Symfony\Component\Form\Extension\Core\Type\RepeatedType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.search" class="Symfony\Component\Form\Extension\Core\Type\SearchType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.textarea" class="Symfony\Component\Form\Extension\Core\Type\TextareaType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.text" class="Symfony\Component\Form\Extension\Core\Type\TextType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.time" class="Symfony\Component\Form\Extension\Core\Type\TimeType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.timezone" class="Symfony\Component\Form\Extension\Core\Type\TimezoneType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.url" class="Symfony\Component\Form\Extension\Core\Type\UrlType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.button" class="Symfony\Component\Form\Extension\Core\Type\ButtonType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.submit" class="Symfony\Component\Form\Extension\Core\Type\SubmitType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.reset" class="Symfony\Component\Form\Extension\Core\Type\ResetType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<service id="form.type.currency" class="Symfony\Component\Form\Extension\Core\Type\CurrencyType">
<tag name="form.type" />
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0.</deprecated>
</service>
<!-- FormTypeHttpFoundationExtension -->
@@ -12,6 +12,7 @@
<argument>%form.type_extension.csrf.field_name%</argument>
<argument type="service" id="translator.default" />
<argument>%validator.translation_domain%</argument>
<argument type="service" id="form.server_params" />
</service>
</services>
</container>
@@ -8,6 +8,7 @@
<service id="property_accessor" class="Symfony\Component\PropertyAccess\PropertyAccessor" >
<argument /> <!-- magicCall, set by the extension -->
<argument /> <!-- throwExceptionOnInvalidIndex, set by the extension -->
<argument type="service" id="cache.property_access" on-invalid="ignore" />
</service>
</services>
</container>
@@ -15,7 +15,7 @@
<!-- Extractor -->
<service id="property_info.reflection_extractor" class="Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor" public="false">
<tag name="property_info.list_extractor" priority="-1000" />
<tag name="property_info.type_extractor" priority="-1000" />
<tag name="property_info.type_extractor" priority="-1002" />
<tag name="property_info.access_extractor" priority="-1000" />
</service>
</services>
@@ -8,11 +8,12 @@
<xsd:element name="config" type="config" />
<xsd:complexType name="config">
<xsd:all>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="assets" type="assets" minOccurs="0" maxOccurs="1" />
<xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" />
<xsd:element name="csrf-protection" type="csrf_protection" minOccurs="0" maxOccurs="1" />
<xsd:element name="esi" type="esi" minOccurs="0" maxOccurs="1" />
<xsd:element name="ssi" type="ssi" minOccurs="0" maxOccurs="1" />
<xsd:element name="fragments" type="fragments" minOccurs="0" maxOccurs="1" />
<xsd:element name="profiler" type="profiler" minOccurs="0" maxOccurs="1" />
<xsd:element name="router" type="router" minOccurs="0" maxOccurs="1" />
@@ -25,7 +26,9 @@
<xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" />
<xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" />
<xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" />
</xsd:all>
<xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
<xsd:element name="workflow" type="workflow" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
<xsd:attribute name="http-method-override" type="xsd:boolean" />
<xsd:attribute name="trusted-proxies" type="xsd:string" />
@@ -55,6 +58,10 @@
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="ssi">
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="fragments">
<xsd:attribute name="enabled" type="xsd:boolean" />
<xsd:attribute name="path" type="xsd:string" />
@@ -103,6 +110,7 @@
<xsd:attribute name="gc-maxlifetime" type="xsd:string" />
<xsd:attribute name="gc-divisor" type="xsd:string" />
<xsd:attribute name="gc-probability" type="xsd:string" />
<xsd:attribute name="use-strict-mode" type="xsd:boolean" />
<xsd:attribute name="save-path" type="xsd:string" />
</xsd:complexType>
@@ -126,6 +134,7 @@
</xsd:sequence>
<xsd:attribute name="base-path" type="xsd:string" />
<xsd:attribute name="version-strategy" type="xsd:string" />
<xsd:attribute name="version" type="xsd:string" />
<xsd:attribute name="version-format" type="xsd:string" />
</xsd:complexType>
@@ -137,6 +146,7 @@
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="base-path" type="xsd:string" />
<xsd:attribute name="version-strategy" type="xsd:string" />
<xsd:attribute name="version" type="xsd:string" />
<xsd:attribute name="version-format" type="xsd:string" />
</xsd:complexType>
@@ -144,10 +154,11 @@
<xsd:complexType name="templating">
<xsd:sequence>
<xsd:element name="loader" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="engine" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
<xsd:element name="engine" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="form" type="form-resources" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="enabled" type="xsd:boolean" />
<xsd:attribute name="cache" type="xsd:string" />
<xsd:attribute name="hinclude-default-template" type="xsd:string" />
</xsd:complexType>
@@ -183,6 +194,7 @@
<xsd:attribute name="cache" type="xsd:string" />
<xsd:attribute name="debug" type="xsd:string" />
<xsd:attribute name="file-cache-dir" type="xsd:string" />
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="property_access">
@@ -200,4 +212,67 @@
<xsd:complexType name="property_info">
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="cache">
<xsd:sequence>
<xsd:element name="app" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="system" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="directory" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="default-doctrine-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="default-psr6-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="default-redis-provider" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="pool" type="cache_pool" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="cache_pool">
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="adapter" type="xsd:string" />
<xsd:attribute name="public" type="xsd:boolean" />
<xsd:attribute name="default-lifetime" type="xsd:integer" />
<xsd:attribute name="provider" type="xsd:string" />
<xsd:attribute name="clearer" type="xsd:string" />
</xsd:complexType>
<xsd:complexType name="workflow">
<xsd:sequence>
<xsd:element name="marking-store" type="marking_store" />
<xsd:element name="support" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
<xsd:element name="place" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
<xsd:element name="transition" type="transition" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="type" type="workflow_type" />
<xsd:attribute name="initial-place" type="xsd:string" />
</xsd:complexType>
<xsd:complexType name="marking_store">
<xsd:sequence>
<xsd:element name="argument" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="type" type="marking_store_type" />
<xsd:attribute name="service" type="xsd:string" />
</xsd:complexType>
<xsd:simpleType name="marking_store_type">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="multiple_state" />
<xsd:enumeration value="single_state" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="transition">
<xsd:sequence>
<xsd:element name="from" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
<xsd:element name="to" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
<xsd:simpleType name="workflow_type">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="state_machine" />
<xsd:enumeration value="workflow" />
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
@@ -14,6 +14,7 @@
<service id="security.csrf.token_manager" class="Symfony\Component\Security\Csrf\CsrfTokenManager">
<argument type="service" id="security.csrf.token_generator" />
<argument type="service" id="security.csrf.token_storage" />
<argument type="service" id="request_stack" on-invalid="ignore" />
</service>
</services>
</container>
@@ -5,6 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="serializer.mapping.cache.file">%kernel.cache_dir%/serialization.php</parameter>
<parameter key="serializer.mapping.cache.prefix" />
</parameters>
@@ -21,11 +22,17 @@
<argument type="service" id="serializer.mapping.class_metadata_factory" />
<argument>null</argument> <!-- name converter -->
<argument type="service" id="serializer.property_accessor" />
<argument type="service" id="property_info" on-invalid="ignore" />
<!-- Run after all custom serializers -->
<!-- Run after all custom normalizers -->
<tag name="serializer.normalizer" priority="-1000" />
</service>
<service id="serializer.denormalizer.array" class="Symfony\Component\Serializer\Normalizer\ArrayDenormalizer" public="false">
<!-- Run before the object normalizer -->
<tag name="serializer.normalizer" priority="-990" />
</service>
<!-- Loader -->
<service id="serializer.mapping.chain_loader" class="Symfony\Component\Serializer\Mapping\Loader\LoaderChain" public="false">
<argument type="collection" />
@@ -38,10 +45,28 @@
</service>
<!-- Cache -->
<service id="serializer.mapping.cache.apc" class="Doctrine\Common\Cache\ApcCache" public="false">
<service id="serializer.mapping.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer" public="false">
<argument type="collection" /><!-- Loaders injected by the extension -->
<argument>%serializer.mapping.cache.file%</argument>
<argument type="service" id="cache.serializer" />
<tag name="kernel.cache_warmer" />
</service>
<service id="serializer.mapping.cache.symfony" class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
<factory class="Symfony\Component\Cache\Adapter\PhpArrayAdapter" method="create" />
<argument>%serializer.mapping.cache.file%</argument>
<argument type="service" id="cache.serializer" />
</service>
<service id="serializer.mapping.cache.doctrine.apc" class="Doctrine\Common\Cache\ApcCache" public="false">
<call method="setNamespace">
<argument>%serializer.mapping.cache.prefix%</argument>
</call>
<deprecated>The "%service_id%" service is deprecated since Symfony 3.2 and will be removed in 4.0. APCu should now be automatically used when available.</deprecated>
</service>
<service id="serializer.mapping.cache.apc" parent="serializer.mapping.cache.doctrine.apc">
<deprecated>The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. APCu should now be automatically used when available.</deprecated>
</service>
<!-- Encoders -->
@@ -55,5 +80,12 @@
<!-- Name converter -->
<service id="serializer.name_converter.camel_case_to_snake_case" class="Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter" public="false" />
<!-- PropertyInfo extractor -->
<service id="property_info.serializer_extractor" class="Symfony\Component\PropertyInfo\Extractor\SerializerExtractor" public="false">
<argument type="service" id="serializer.mapping.class_metadata_factory" />
<tag name="property_info.list_extractor" priority="-999" />
</service>
</services>
</container>
@@ -13,6 +13,7 @@
<argument type="service" id="event_dispatcher" />
<argument type="service" id="controller_resolver" />
<argument type="service" id="request_stack" />
<argument type="service" id="argument_resolver" />
</service>
<service id="request_stack" class="Symfony\Component\HttpFoundation\RequestStack" />
@@ -23,6 +24,16 @@
<service id="kernel.class_cache.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\ClassCacheCacheWarmer">
<tag name="kernel.cache_warmer" />
<argument type="collection">
<argument>Symfony\Component\HttpFoundation\ParameterBag</argument>
<argument>Symfony\Component\HttpFoundation\HeaderBag</argument>
<argument>Symfony\Component\HttpFoundation\FileBag</argument>
<argument>Symfony\Component\HttpFoundation\ServerBag</argument>
<argument>Symfony\Component\HttpFoundation\Request</argument>
<argument>Symfony\Component\HttpKernel\Kernel</argument>
<argument>Symfony\Component\ClassLoader\ClassCollectionLoader</argument>
<argument>Symfony\Component\ClassLoader\ApcClassLoader</argument>
</argument>
</service>
<service id="cache_clearer" class="Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer">
@@ -44,7 +44,7 @@
<service id="templating.helper.code" class="Symfony\Bundle\FrameworkBundle\Templating\Helper\CodeHelper">
<tag name="templating.helper" alias="code" />
<argument>%templating.helper.code.file_link_format%</argument>
<argument type="service" id="debug.file_link_formatter"></argument>
<argument>%kernel.root_dir%</argument>
<argument>%kernel.charset%</argument>
</service>
@@ -128,8 +128,14 @@
<service id="translation.writer" class="Symfony\Component\Translation\Writer\TranslationWriter"/>
<service id="translation.warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer" public="false">
<argument type="service" id="translator" />
<argument type="service" id="service_container" />
<tag name="kernel.cache_warmer" />
</service>
<service id="translator_listener" class="Symfony\Component\HttpKernel\EventListener\TranslatorListener">
<argument type="service" id="translator" />
<argument type="service" id="request_stack" />
<tag name="kernel.event_subscriber" />
</service>
</services>
</container>
@@ -6,6 +6,7 @@
<parameters>
<parameter key="validator.mapping.cache.prefix" />
<parameter key="validator.mapping.cache.file">%kernel.cache_dir%/validation.php</parameter>
</parameters>
<services>
@@ -28,6 +29,23 @@
<service id="validator.mapping.class_metadata_factory" alias="validator" public="false" />
<service id="validator.mapping.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\ValidatorCacheWarmer" public="false">
<argument type="service" id="validator.builder" />
<argument>%validator.mapping.cache.file%</argument>
<argument type="service" id="cache.validator" />
<tag name="kernel.cache_warmer" />
</service>
<service id="validator.mapping.cache.symfony" class="Symfony\Component\Validator\Mapping\Cache\Psr6Cache" public="false">
<argument type="service">
<service class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
<factory class="Symfony\Component\Cache\Adapter\PhpArrayAdapter" method="create" />
<argument>%validator.mapping.cache.file%</argument>
<argument type="service" id="cache.validator" />
</service>
</argument>
</service>
<service id="validator.mapping.cache.doctrine.apc" class="Symfony\Component\Validator\Mapping\Cache\DoctrineCache" public="false">
<argument type="service">
<service class="Doctrine\Common\Cache\ApcCache">
+23 -6
View File
@@ -17,6 +17,29 @@
<argument type="service" id="logger" on-invalid="ignore" />
</service>
<service id="argument_metadata_factory" class="Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory" public="false" />
<service id="argument_resolver" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver" public="false">
<argument type="service" id="argument_metadata_factory" />
<argument type="collection" />
</service>
<service id="argument_resolver.request_attribute" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver" public="false">
<tag name="controller.argument_value_resolver" priority="100" />
</service>
<service id="argument_resolver.request" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver" public="false">
<tag name="controller.argument_value_resolver" priority="50" />
</service>
<service id="argument_resolver.default" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver" public="false">
<tag name="controller.argument_value_resolver" priority="-100" />
</service>
<service id="argument_resolver.variadic" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver" public="false">
<tag name="controller.argument_value_resolver" priority="-150" />
</service>
<service id="response_listener" class="Symfony\Component\HttpKernel\EventListener\ResponseListener">
<tag name="kernel.event_subscriber" />
<argument>%kernel.charset%</argument>
@@ -33,12 +56,6 @@
<argument type="service" id="router" on-invalid="ignore" />
</service>
<service id="translator_listener" class="Symfony\Component\HttpKernel\EventListener\TranslatorListener">
<argument type="service" id="translator" />
<argument type="service" id="request_stack" />
<tag name="kernel.event_subscriber" />
</service>
<service id="validate_request_listener" class="Symfony\Component\HttpKernel\EventListener\ValidateRequestListener">
<tag name="kernel.event_subscriber" />
</service>
@@ -1,138 +0,0 @@
/*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.1.2
build: 56
*/
.sf-reset div,.sf-reset dl,.sf-reset dt,.sf-reset dd,.sf-reset ul,.sf-reset ol,.sf-reset li,.sf-reset h1,.sf-reset h2,.sf-reset h3,.sf-reset h4,.sf-reset h5,.sf-reset h6,.sf-reset pre,.sf-reset code,.sf-reset form,.sf-reset fieldset,.sf-reset legend,.sf-reset input,.sf-reset textarea,.sf-reset p,.sf-reset blockquote,.sf-reset th,.sf-reset td{margin:0;padding:0;}.sf-reset table{border-collapse:collapse;border-spacing:0;}.sf-reset fieldset,.sf-reset img{border:0;}.sf-reset address,.sf-reset caption,.sf-reset cite,.sf-reset code,.sf-reset dfn,.sf-reset em,.sf-reset strong,.sf-reset th,.sf-reset var{font-style:normal;font-weight:normal;}.sf-reset li{list-style:none;}.sf-reset caption,.sf-reset th{text-align:left;}.sf-reset h1,.sf-reset h2,.sf-reset h3,.sf-reset h4,.sf-reset h5,.sf-reset h6{font-size:100%;font-weight:normal;}.sf-reset q:before,.sf-reset q:after{content:'';}.sf-reset abbr,.sf-reset acronym{border:0;font-variant:normal;}.sf-reset sup{vertical-align:text-top;}.sf-reset sub{vertical-align:text-bottom;}.sf-reset input,.sf-reset textarea,.sf-reset select{font-family:inherit;font-size:inherit;font-weight:inherit;}.sf-reset input,.sf-reset textarea,.sf-reset select{font-size:100%;}.sf-reset legend{color:#000;}
.sf-reset abbr {
border-bottom: 1px dotted #000;
cursor: help;
}
.sf-reset p {
font-size: 14px;
line-height: 20px;
padding-bottom: 20px;
}
.sf-reset strong {
color: #313131;
font-weight: bold;
}
.sf-reset a {
color: #6c6159;
}
.sf-reset a img {
border: none;
}
.sf-reset a:hover {
text-decoration: underline;
}
.sf-reset em {
font-style: italic;
}
.sf-reset h2,
.sf-reset h3 {
font-weight: bold;
}
.sf-reset h1 {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 20px;
color: #313131;
word-break: break-all;
}
.sf-reset li {
padding-bottom: 10px;
}
.sf-reset .block {
-moz-border-radius: 16px;
-webkit-border-radius: 16px;
border-radius: 16px;
margin-bottom: 20px;
background-color: #FFFFFF;
border: 1px solid #dfdfdf;
padding: 40px 50px;
word-break: break-all;
}
.sf-reset h2 {
font-size: 16px;
font-family: Arial, Helvetica, sans-serif;
}
.sf-reset li a {
background: none;
color: #868686;
text-decoration: none;
}
.sf-reset li a:hover {
background: none;
color: #313131;
text-decoration: underline;
}
.sf-reset ol {
padding: 10px 0;
}
.sf-reset ol li {
list-style: decimal;
margin-left: 20px;
padding: 2px;
padding-bottom: 20px;
}
.sf-reset ol ol li {
list-style-position: inside;
margin-left: 0;
white-space: nowrap;
font-size: 12px;
padding-bottom: 0;
}
.sf-reset li .selected {
background-color: #ffd;
}
.sf-button {
display: -moz-inline-box;
display: inline-block;
text-align: center;
vertical-align: middle;
border: 0;
background: transparent none;
text-transform: uppercase;
cursor: pointer;
font: bold 11px Arial, Helvetica, sans-serif;
}
.sf-button span {
text-decoration: none;
display: block;
height: 28px;
float: left;
}
.sf-button .border-l {
text-decoration: none;
display: block;
height: 28px;
float: left;
padding: 0 0 0 7px;
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQtJREFUeNpiPHnyJAMakARiByDWYEGT8ADiYGVlZStubm5xlv///4MEQYoKZGRkQkRERLRYWVl5wYJQyXBZWdkwCQkJUxAHKgaWlAHSLqKiosb//v1DsYMFKGCvoqJiDmQzwXTAJYECulxcXNLoumCSoszMzDzoumDGghQwYZUECWIzkrAkSIIGOmlkLI10AiX//P379x8jIyMTNmPf/v79+ysLCwsvuiQoNi5//fr1Kch4dAyS3P/gwYMTQBP+wxwHw0xA4gkQ73v9+vUZdJ2w1Lf82bNn4iCHCQoKasHsZw4ODgbRIL8c+/Lly5M3b978Y2dn5wC6npkFLXnsAOKLjx49AmUHLYAAAwBoQubG016R5wAAAABJRU5ErkJggg==) no-repeat top left;
}
.sf-button .border-r {
padding: 0 7px 0 0;
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAR1JREFUeNpiPHnyZCMDA8MNID5gZmb2nAEJMH7//v3N169fX969e/cYkL8WqGAHXPLv37//QYzfv39/fvPmzbUnT56sAXInmJub/2H5/x8sx8DCwsIrISFhDmQyPX78+CmQXs70798/BmQsKipqBNTgdvz4cWkmkE5kDATMioqKZkCFdiwg1eiAi4tLGqhQF24nMmBmZuYEigth1QkEbEBxTlySYPvJkwSJ00AnjYylgU6gxB8g/oFVEphkvgLF32KNMmCCewYUv4qhEyj47+HDhyeBzIMYOoEp8CxQw56wsLAncJ1//vz5/P79+2svX74EJc2V4BT58+fPd8CE/QKYHMGJOiIiAp6oWW7evDkNSF8DZYfIyEiU7AAQYACJ2vxVdJW4eQAAAABJRU5ErkJggg==) right top no-repeat;
}
.sf-button .btn-bg {
padding: 0 14px;
color: #636363;
line-height: 28px;
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAcCAYAAACgXdXMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAClJREFUeNpiPnny5EKGf//+/Wf6//8/A4QAcrGzKCZwGc9sa2urBBBgAIbDUoYVp9lmAAAAAElFTkSuQmCC) repeat-x top left;
}
.sf-button:hover .border-l,
.sf-button-selected .border-l {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAR9JREFUeNpi/P//PwMyOHfunDqQSgNiexZkibNnzxYBqZa3HOs5v7PcYQBLnjlzhg1IbfzIdsTjA/t+ht9Mr8GKwZL//v3r+sB+0OMN+zqIEf8gFMvJkyd1gXTOa9YNDP//otrPAtSV/Jp9HfPff78Z0AEL0LUeXxivMfxD0wXTqfjj/2ugkf+wSrL9/YtpJEyS4S8WI5Ek/+GR/POPFjr//cenE6/kP9q4Fo/kr39/mdj+M/zFkGQCSj5i+ccPjLJ/GBgkuYOHQR1sNDpmAkb2LBmWwL///zKCIxwZM0VHR18G6p4uxeLLAA4tJMwEshiou1iMxXaHLGswA+t/YbhORuQUv2DBAnCifvxzI+enP3dQJUFg/vz5sOzgBBBgAPxX9j0YnH4JAAAAAElFTkSuQmCC) no-repeat top left;
}
.sf-button:hover .border-r,
.sf-button-selected .border-r {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT5JREFUeNpiPHv27BkGBoaDQDzLyMjoJgMSYHrM3WX8hn1d0f///88DFRYhSzIuv2X5H8Rg/SfKIPDTkYH/l80OINffxMTkF9O/f/8ZQPgnwyuGl+wrGd6x7vf49+9fO9jYf3+Bkkj4NesmBqAV+SdPntQC6vzHgIz//gOawbqOGchOxtAJwp8Zr4F0e7D8/fuPAR38/P8eZIo0yz8skv8YvoIk+YE6/zNgAyD7sRqLkPzzjxY6/+HS+R+fTkZ8djLh08lCUCcuSWawJGbwMTGwg7zyBatX2Bj5QZKPsBrLzaICktzN8g/NWEYGZgYZjoC/wMiei5FMpFh8QPSU6Ojoy3Cd7EwiDBJsDgxiLNY7gLrKQGIsHAxSDHxAO2TZ/b8D+TVxcXF9MCtYtLiKLgDpfUDVsxITE1GyA0CAAQA2E/N8VuHyAAAAAABJRU5ErkJggg==) right top no-repeat;
}
.sf-button:hover .btn-bg,
.sf-button-selected .btn-bg {
color: #FFFFFF;
text-shadow:0 1px 1px #6b9311;
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAcCAIAAAAvP0KbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpiPnv2LNMdvlymf///M/37B8R/QfQ/MP33L4j+B6Qh7L9//sHpf2h8MA1V+w/KRjYLaDaLCU8vQIABAFO3TxZriO4yAAAAAElFTkSuQmCC) repeat-x top left;
}
@@ -1,112 +0,0 @@
.sf-reset .traces {
padding-bottom: 14px;
}
.sf-reset .traces li {
font-size: 12px;
color: #868686;
padding: 5px 4px;
list-style-type: decimal;
margin-left: 20px;
}
.sf-reset #logs .traces li.error {
font-style: normal;
color: #AA3333;
background: #f9ecec;
}
.sf-reset #logs .traces li.warning {
font-style: normal;
background: #ffcc00;
}
/* fix for Opera not liking empty <li> */
.sf-reset .traces li:after {
content: "\00A0";
}
.sf-reset .trace {
border: 1px solid #D3D3D3;
padding: 10px;
overflow: auto;
margin: 10px 0 20px;
}
.sf-reset .block-exception {
-moz-border-radius: 16px;
-webkit-border-radius: 16px;
border-radius: 16px;
margin-bottom: 20px;
background-color: #f6f6f6;
border: 1px solid #dfdfdf;
padding: 30px 28px;
word-wrap: break-word;
overflow: hidden;
}
.sf-reset .block-exception div {
color: #313131;
font-size: 10px;
}
.sf-reset .block-exception-detected .illustration-exception,
.sf-reset .block-exception-detected .text-exception {
float: left;
}
.sf-reset .block-exception-detected .illustration-exception {
width: 152px;
}
.sf-reset .block-exception-detected .text-exception {
width: 670px;
padding: 30px 44px 24px 46px;
position: relative;
}
.sf-reset .text-exception .open-quote,
.sf-reset .text-exception .close-quote {
position: absolute;
}
.sf-reset .open-quote {
top: 0;
left: 0;
}
.sf-reset .close-quote {
bottom: 0;
right: 50px;
}
.sf-reset .block-exception p {
font-family: Arial, Helvetica, sans-serif;
}
.sf-reset .block-exception p a,
.sf-reset .block-exception p a:hover {
color: #565656;
}
.sf-reset .logs h2 {
float: left;
width: 654px;
}
.sf-reset .error-count {
float: right;
width: 170px;
text-align: right;
}
.sf-reset .error-count span {
display: inline-block;
background-color: #aacd4e;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
padding: 4px;
color: white;
margin-right: 2px;
font-size: 11px;
font-weight: bold;
}
.sf-reset .toggle {
vertical-align: middle;
}
.sf-reset .linked ul,
.sf-reset .linked li {
display: inline;
}
.sf-reset #output-content {
color: #000;
font-size: 12px;
}
.sf-reset #traces-text pre {
white-space: pre;
font-size: 12px;
font-family: monospace;
}
@@ -1,68 +0,0 @@
html {
background: #eee;
}
body {
font: 11px Verdana, Arial, sans-serif;
color: #333;
}
.sf-reset, .sf-reset .block, .sf-reset #message {
margin: auto;
}
img {
border: 0;
}
.clear {
clear: both;
height: 0;
font-size: 0;
line-height: 0;
}
.clear-fix:after {
content: "\0020";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clear-fix {
display: inline-block;
}
* html .clear-fix {
height: 1%;
}
.clear-fix {
display: block;
}
.header {
padding: 30px 30px 20px 30px;
}
.header-logo {
float: left;
}
.search {
float: right;
padding-top: 20px;
}
.search label {
line-height: 28px;
vertical-align: middle;
}
.search input {
width: 195px;
font-size: 12px;
border: 1px solid #dadada;
background: #fff url(data:image/gif;base64,R0lGODlhAQAFAKIAAPX19e/v7/39/fr6+urq6gAAAAAAAAAAACH5BAAAAAAALAAAAAABAAUAAAMESAEjCQA7) repeat-x left top;
padding: 5px 6px;
color: #565656;
}
.search input[type="search"] {
-webkit-appearance: textfield;
}
#content {
width: 970px;
margin: 0 auto;
}
#content pre {
white-space: normal;
font-family: Arial, Helvetica, sans-serif;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1,6 +1,6 @@
id="<?php echo $view->escape($id) ?>" name="<?php echo $view->escape($full_name) ?>" <?php if ($disabled): ?>disabled="disabled" <?php endif ?>
<?php foreach ($attr as $k => $v): ?>
<?php if (in_array($v, array('placeholder', 'title'), true)): ?>
<?php if (in_array($k, array('placeholder', 'title'), true)): ?>
<?php printf('%s="%s" ', $view->escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
<?php elseif ($v === true): ?>
<?php printf('%s="%s" ', $view->escape($k), $view->escape($k)) ?>
@@ -1,4 +1,3 @@
id="<?php echo $view->escape($id) ?>" name="<?php echo $view->escape($full_name) ?>"
<?php if ($disabled): ?>disabled="disabled" <?php endif ?>
<?php foreach ($choice_attr as $k => $v): ?>
<?php if ($v === true): ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?>
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'password')) ?>
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'password')) ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> %
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'text')) ?> %
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'reset')) ?>
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'reset')) ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'search')) ?>
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'search')) ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'submit')) ?>
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'submit')) ?>
@@ -1 +1 @@
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'url')) ?>
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'url')) ?>
@@ -1,6 +1,6 @@
<?php if (!empty($id)): ?>id="<?php echo $view->escape($id) ?>" <?php endif ?>
<?php foreach ($attr as $k => $v): ?>
<?php if (in_array($v, array('placeholder', 'title'), true)): ?>
<?php if (in_array($k, array('placeholder', 'title'), true)): ?>
<?php printf('%s="%s" ', $view->escape($k), $view->escape(false !== $translation_domain ? $view['translator']->trans($v, array(), $translation_domain) : $v)) ?>
<?php elseif ($v === true): ?>
<?php printf('%s="%s" ', $view->escape($k), $view->escape($k)) ?>
@@ -20,7 +20,7 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface;
* DelegatingLoader delegates route loading to other loaders using a loader resolver.
*
* This implementation resolves the _controller attribute from the short notation
* to the fully-qualified form (from a:b:c to class:method).
* to the fully-qualified form (from a:b:c to class::method).
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@@ -75,15 +75,17 @@ class DelegatingLoader extends BaseDelegatingLoader
}
foreach ($collection->all() as $route) {
if ($controller = $route->getDefault('_controller')) {
try {
$controller = $this->parser->parse($controller);
} catch (\InvalidArgumentException $e) {
// unable to optimize unknown notation
}
$route->setDefault('_controller', $controller);
if (!$controller = $route->getDefault('_controller')) {
continue;
}
try {
$controller = $this->parser->parse($controller);
} catch (\InvalidArgumentException $e) {
// unable to optimize unknown notation
}
$route->setDefault('_controller', $controller);
}
return $collection;
+4 -1
View File
@@ -146,6 +146,10 @@ class Router extends BaseRouter implements WarmableInterface
return '%%';
}
if (preg_match('/^env\(\w+\)$/', $match[1])) {
throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1]));
}
$resolved = $container->getParameter($match[1]);
if (is_string($resolved) || is_numeric($resolved)) {
@@ -160,7 +164,6 @@ class Router extends BaseRouter implements WarmableInterface
gettype($resolved)
)
);
}, $value);
return str_replace('%%', '%', $escapedValue);
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
use Symfony\Component\Templating\Helper\Helper;
/**
@@ -27,9 +28,9 @@ class CodeHelper extends Helper
/**
* Constructor.
*
* @param string $fileLinkFormat The format for links to source files
* @param string $rootDir The project root directory
* @param string $charset The charset
* @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
* @param string $rootDir The project root directory
* @param string $charset The charset
*/
public function __construct($fileLinkFormat, $rootDir, $charset)
{
@@ -132,7 +133,7 @@ class CodeHelper extends Helper
$code = @highlight_file($file, true);
// remove main code/span tags
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
$content = preg_split('#<br />#', $code);
$content = explode('<br />', $code);
$lines = array();
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; ++$i) {
@@ -185,8 +186,8 @@ class CodeHelper extends Helper
*/
public function getFileLink($file, $line)
{
if ($this->fileLinkFormat && is_file($file)) {
return strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
if ($fmt = $this->fileLinkFormat) {
return is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line);
}
return false;
@@ -24,6 +24,8 @@ class TemplateLocator implements FileLocatorInterface
protected $locator;
protected $cache;
private $cacheHits = array();
/**
* Constructor.
*
@@ -32,7 +34,7 @@ class TemplateLocator implements FileLocatorInterface
*/
public function __construct(FileLocatorInterface $locator, $cacheDir = null)
{
if (null !== $cacheDir && is_file($cache = $cacheDir.'/templates.php')) {
if (null !== $cacheDir && file_exists($cache = $cacheDir.'/templates.php')) {
$this->cache = require $cache;
}
@@ -71,12 +73,15 @@ class TemplateLocator implements FileLocatorInterface
$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);
}
@@ -55,7 +55,7 @@ class TemplateNameParser extends BaseTemplateNameParser
throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.', $name));
}
if (!preg_match('/^(?:([^:]*):([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches) || $this->isAbsolutePath($name) || 0 === strpos($name, '@')) {
if ($this->isAbsolutePath($name) || !preg_match('/^(?:([^:]*):([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches) || 0 === strpos($name, '@')) {
return parent::parse($name);
}
@@ -74,6 +74,12 @@ class TemplateNameParser extends BaseTemplateNameParser
private function isAbsolutePath($file)
{
return (bool) preg_match('#^(?:/|[a-zA-Z]:)#', $file);
$isAbsolute = (bool) preg_match('#^(?:/|[a-zA-Z]:)#', $file);
if ($isAbsolute) {
@trigger_error('Absolute template path support is deprecated since Symfony 3.1 and will be removed in 4.0.', E_USER_DEPRECATED);
}
return $isAbsolute;
}
}
+2 -1
View File
@@ -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 @@ use Symfony\Component\HttpKernel\KernelInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class KernelTestCase extends \PHPUnit_Framework_TestCase
abstract class KernelTestCase extends TestCase
{
protected static $class;
@@ -57,11 +57,10 @@ class CacheClearCommandTest extends TestCase
// 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));
});
}
@@ -81,6 +80,6 @@ class CacheClearCommandTest extends TestCase
}
}
$this->assertTrue($found, 'Kernel file should present as resource');
$this->assertRegExp(sprintf('/\'kernel.name\'\s*=>\s*\'%s\'/', $this->kernel->getName()), file_get_contents($containerFile), 'kernel.name is properly set on the dumped container');
$this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', get_class($this->kernel->getContainer())), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container');
}
}
@@ -11,13 +11,15 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
use Symfony\Component\Console\Application;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class RouterDebugCommandTest extends \PHPUnit_Framework_TestCase
class RouterDebugCommandTest extends TestCase
{
public function testDebugAllRoutes()
{
@@ -50,45 +52,51 @@ class RouterDebugCommandTest extends \PHPUnit_Framework_TestCase
*/
private function createCommandTester()
{
$application = new Application();
$application = new Application($this->getKernel());
$command = new RouterDebugCommand();
$command->setContainer($this->getContainer());
$application->add($command);
return new CommandTester($application->find('debug:router'));
}
private function getContainer()
private function getKernel()
{
$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')
->will($this->returnValue($routeCollection))
;
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader')
->disableOriginalConstructor()
->getMock();
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('has')
->with('router')
->will($this->returnValue(true))
;
$container
->expects($this->any())
->method('get')
->will($this->returnValueMap(array(
array('router', 1, $router),
array('controller_name_converter', 1, $loader),
)));
->with('router')
->willReturn($router)
;
return $container;
$kernel = $this->getMockBuilder(KernelInterface::class)->getMock();
$kernel
->expects($this->any())
->method('getContainer')
->willReturn($container)
;
$kernel
->expects($this->once())
->method('getBundles')
->willReturn(array())
;
return $kernel;
}
}
@@ -11,15 +11,17 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Command;
use Symfony\Component\Console\Application;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand;
use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
class RouterMatchCommandTest extends \PHPUnit_Framework_TestCase
class RouterMatchCommandTest extends TestCase
{
public function testWithMatchPath()
{
@@ -44,25 +46,19 @@ class RouterMatchCommandTest extends \PHPUnit_Framework_TestCase
*/
private function createCommandTester()
{
$application = new Application();
$command = new RouterMatchCommand();
$command->setContainer($this->getContainer());
$application->add($command);
$command = new RouterDebugCommand();
$command->setContainer($this->getContainer());
$application->add($command);
$application = new Application($this->getKernel());
$application->add(new RouterMatchCommand());
$application->add(new RouterDebugCommand());
return new CommandTester($application->find('router:match'));
}
private function getContainer()
private function getKernel()
{
$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')
@@ -74,23 +70,29 @@ class RouterMatchCommandTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($requestContext))
;
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader')
->disableOriginalConstructor()
->getMock();
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->expects($this->atLeastOnce())
->method('has')
->with('router')
->will($this->returnValue(true));
$container->method('get')
->will($this->returnValueMap(array(
array('router', 1, $router),
array('controller_name_converter', 1, $loader),
$container
->expects($this->any())
->method('get')
->willReturn($router);
)));
$kernel = $this->getMockBuilder(KernelInterface::class)->getMock();
$kernel
->expects($this->any())
->method('getContainer')
->willReturn($container)
;
$kernel
->expects($this->once())
->method('getBundles')
->willReturn(array())
;
return $container;
return $kernel;
}
}
@@ -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 @@ class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
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 @@ class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
*/
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,28 +131,28 @@ class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
->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')
->will(
$this->returnCallback(function ($path, $catalogue) use ($extractedMessages) {
$catalogue->add($extractedMessages);
$catalogue->add($extractedMessages);
})
);
$loader = $this->getMock('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader');
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock();
$loader
->expects($this->any())
->method('loadMessages')
->will(
$this->returnCallback(function ($path, $catalogue) use ($loadedMessages) {
$catalogue->add($loadedMessages);
$catalogue->add($loadedMessages);
})
);
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 @@ class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
->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 @@ class TranslationDebugCommandTest extends \PHPUnit_Framework_TestCase
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')
@@ -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,26 +19,50 @@ use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\DependencyInjection;
use Symfony\Component\HttpKernel;
class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
class TranslationUpdateCommandTest extends TestCase
{
private $fs;
private $translationDir;
public function testDumpMessagesAndClean()
{
$tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo')));
$tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'))));
$tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true));
$this->assertRegExp('/foo/', $tester->getDisplay());
$this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay());
}
public function testDumpTwoMessagesAndClean()
{
$tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo', 'bar' => 'bar'))));
$tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true));
$this->assertRegExp('/foo/', $tester->getDisplay());
$this->assertRegExp('/bar/', $tester->getDisplay());
$this->assertRegExp('/2 messages were successfully extracted/', $tester->getDisplay());
}
public function testDumpMessagesForSpecificDomain()
{
$tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar'))));
$tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true, '--domain' => 'mydomain'));
$this->assertRegExp('/bar/', $tester->getDisplay());
$this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay());
}
public function testWriteMessages()
{
$tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo')));
$tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'))));
$tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--force' => true));
$this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay());
}
public function testWriteMessagesForSpecificDomain()
{
$tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar'))));
$tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--force' => true, '--domain' => 'mydomain'));
$this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay());
}
protected function setUp()
{
$this->fs = new Filesystem();
@@ -76,27 +101,29 @@ class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
->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')
->will(
$this->returnCallback(function ($path, $catalogue) use ($extractedMessages) {
$catalogue->add($extractedMessages);
foreach ($extractedMessages as $domain => $messages) {
$catalogue->add($messages, $domain);
}
})
);
$loader = $this->getMock('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader');
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock();
$loader
->expects($this->any())
->method('loadMessages')
->will(
$this->returnCallback(function ($path, $catalogue) use ($loadedMessages) {
$catalogue->add($loadedMessages);
$catalogue->add($loadedMessages);
})
);
$writer = $this->getMock('Symfony\Component\Translation\Writer\TranslationWriter');
$writer = $this->getMockBuilder('Symfony\Component\Translation\Writer\TranslationWriter')->getMock();
$writer
->expects($this->any())
->method('getFormats')
@@ -105,7 +132,7 @@ class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
);
if (null === $kernel) {
$kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
$kernel
->expects($this->any())
->method('getBundle')
@@ -120,7 +147,7 @@ class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
->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')
@@ -137,7 +164,7 @@ class TranslationUpdateCommandTest extends \PHPUnit_Framework_TestCase
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')
@@ -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 @@ class ApplicationTest extends TestCase
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 @@ class ApplicationTest extends TestCase
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 @@ class ApplicationTest extends TestCase
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'));
}
@@ -123,12 +115,27 @@ class ApplicationTest extends TestCase
$tester->run(array('command' => 'foo'));
}
public function testBundleCommandCanOverriddeAPreExistingCommandWithTheSameName()
{
$command = new Command('example');
$bundle = $this->createBundleMock(array($command));
$kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
$newCommand = new Command('example');
$application->add($newCommand);
$this->assertSame($newCommand, $application->get('example'));
}
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 +160,7 @@ class ApplicationTest extends TestCase
->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 +174,18 @@ class ApplicationTest extends TestCase
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;
}
}
@@ -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\EventDispatcher\EventDispatcher;
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)
@@ -129,6 +130,7 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
}
abstract protected function getDescriptor();
abstract protected function getFormat();
private function assertDescription($expectedDescription, $describedObject, array $options = array())
@@ -115,6 +115,7 @@ class ObjectsProvider
->addTag('tag1', array('attr1' => 'val1', 'attr2' => 'val2'))
->addTag('tag1', array('attr3' => 'val3'))
->addTag('tag2')
->addMethodCall('setMailer', array(new Reference('mailer')))
->setFactory(array(new Reference('factory.service'), 'get')),
);
}
@@ -157,9 +158,11 @@ class CallableClass
public function __invoke()
{
}
public static function staticMethod()
{
}
public function method()
{
}
@@ -93,7 +93,7 @@ class ControllerNameParserTest extends TestCase
try {
$parser->parse($name);
$this->fail('->parse() throws a \InvalidArgumentException if the string is in the valid format, but not matching class can be found');
$this->fail('->parse() throws a \InvalidArgumentException if the class is found but does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->parse() throws a \InvalidArgumentException if the class is found but does not exist');
}
@@ -108,7 +108,6 @@ class ControllerNameParserTest extends TestCase
}
/**
* @expectedException
* @dataProvider getInvalidBundleNameTests
*/
public function testInvalidBundleName($bundleName, $suggestedBundleName)
@@ -117,6 +116,7 @@ class ControllerNameParserTest extends TestCase
try {
$parser->parse($bundleName);
$this->fail('->parse() throws a \InvalidArgumentException if the bundle does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->parse() throws a \InvalidArgumentException if the bundle does not exist');
@@ -147,7 +147,7 @@ class ControllerNameParserTest extends TestCase
'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 +178,7 @@ class ControllerNameParserTest extends TestCase
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));
@@ -143,7 +143,12 @@ class ControllerResolverTest extends BaseControllerResolverTest
{
// 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);
if (method_exists($this, 'expectException')) {
$this->expectException($exceptionName);
$this->expectExceptionMessageRegExp($exceptionMessage);
} else {
$this->setExpectedExceptionRegExp($exceptionName, $exceptionMessage);
}
$request = Request::create('/');
$request->attributes->set('_controller', $controller);
@@ -179,12 +184,12 @@ class ControllerResolverTest extends BaseControllerResolverTest
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();
}
}
@@ -14,15 +14,20 @@ 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
{
@@ -35,12 +40,12 @@ class ControllerTest extends TestCase
$requestStack = new RequestStack();
$requestStack->push($request);
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$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 = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('get')->will($this->returnValue($requestStack));
$container->expects($this->at(1))->method('get')->will($this->returnValue($kernel));
@@ -86,7 +91,7 @@ class ControllerTest extends TestCase
*/
public function testGetUserWithEmptyContainer()
{
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('has')
@@ -106,13 +111,13 @@ class ControllerTest extends TestCase
*/
private function getContainerWithTokenStorage($token = null)
{
$tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage');
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage')->getMock();
$tokenStorage
->expects($this->once())
->method('getToken')
->will($this->returnValue($token));
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container
->expects($this->once())
->method('has')
@@ -128,12 +133,211 @@ class ControllerTest extends TestCase
return $container;
}
public function testJson()
{
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
$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->getMockBuilder(ContainerInterface::class)->getMock();
$container
->expects($this->once())
->method('has')
->with('serializer')
->will($this->returnValue(true));
$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
->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->getMockBuilder(ContainerInterface::class)->getMock();
$container
->expects($this->once())
->method('has')
->with('serializer')
->will($this->returnValue(true));
$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
->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->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$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->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$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->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$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->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$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 = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(true));
$container->expects($this->at(1))->method('get')->will($this->returnValue($authorizationChecker));
@@ -148,10 +352,10 @@ class ControllerTest extends TestCase
*/
public function testdenyAccessUnlessGranted()
{
$authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
$authorizationChecker = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(false);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(true));
$container->expects($this->at(1))->method('get')->will($this->returnValue($authorizationChecker));
@@ -163,10 +367,10 @@ class ControllerTest extends TestCase
public function testRenderViewTwig()
{
$twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
$twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->willReturn('bar');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -179,10 +383,10 @@ class ControllerTest extends TestCase
public function testRenderTwig()
{
$twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
$twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock();
$twig->expects($this->once())->method('render')->willReturn('bar');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -195,9 +399,9 @@ class ControllerTest extends TestCase
public function testStreamTwig()
{
$twig = $this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock();
$twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock();
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -210,10 +414,10 @@ class ControllerTest extends TestCase
public function testRedirectToRoute()
{
$router = $this->getMock('Symfony\Component\Routing\RouterInterface');
$router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router->expects($this->once())->method('generate')->willReturn('/foo');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('get')->will($this->returnValue($router));
$controller = new TestController();
@@ -228,10 +432,10 @@ class ControllerTest extends TestCase
public function testAddFlash()
{
$flashBag = new FlashBag();
$session = $this->getMock('Symfony\Component\HttpFoundation\Session\Session');
$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock();
$session->expects($this->once())->method('getFlashBag')->willReturn($flashBag);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(true));
$container->expects($this->at(1))->method('get')->will($this->returnValue($session));
@@ -251,10 +455,10 @@ class ControllerTest extends TestCase
public function testIsCsrfTokenValid()
{
$tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface');
$tokenManager = $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock();
$tokenManager->expects($this->once())->method('isTokenValid')->willReturn(true);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(true));
$container->expects($this->at(1))->method('get')->will($this->returnValue($tokenManager));
@@ -266,10 +470,10 @@ class ControllerTest extends TestCase
public function testGenerateUrl()
{
$router = $this->getMock('Symfony\Component\Routing\RouterInterface');
$router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$router->expects($this->once())->method('generate')->willReturn('/foo');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('get')->will($this->returnValue($router));
$controller = new TestController();
@@ -290,10 +494,10 @@ class ControllerTest extends TestCase
public function testRenderViewTemplating()
{
$templating = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface');
$templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
$templating->expects($this->once())->method('render')->willReturn('bar');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -305,10 +509,10 @@ class ControllerTest extends TestCase
public function testRenderTemplating()
{
$templating = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface');
$templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock();
$templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar'));
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -320,9 +524,9 @@ class ControllerTest extends TestCase
public function testStreamTemplating()
{
$templating = $this->getMock('Symfony\Component\Routing\RouterInterface');
$templating = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock();
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$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));
@@ -341,12 +545,12 @@ class ControllerTest extends TestCase
public function testCreateForm()
{
$form = $this->getMock('Symfony\Component\Form\FormInterface');
$form = $this->getMockBuilder('Symfony\Component\Form\FormInterface')->getMock();
$formFactory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
$formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$formFactory->expects($this->once())->method('create')->willReturn($form);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('get')->will($this->returnValue($formFactory));
$controller = new TestController();
@@ -357,12 +561,12 @@ class ControllerTest extends TestCase
public function testCreateFormBuilder()
{
$formBuilder = $this->getMock('Symfony\Component\Form\FormBuilderInterface');
$formBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilderInterface')->getMock();
$formFactory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
$formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$formFactory->expects($this->once())->method('createBuilder')->willReturn($formBuilder);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('get')->will($this->returnValue($formFactory));
$controller = new TestController();
@@ -373,9 +577,9 @@ class ControllerTest extends TestCase
public function testGetDoctrine()
{
$doctrine = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
$doctrine = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock();
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
$container->expects($this->at(0))->method('has')->will($this->returnValue(true));
$container->expects($this->at(1))->method('get')->will($this->returnValue($doctrine));
@@ -408,6 +612,16 @@ class TestController extends Controller
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);
@@ -66,14 +66,14 @@ class RedirectControllerTest extends TestCase
$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 @@ class RedirectControllerTest extends TestCase
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 @@ class RedirectControllerTest extends TestCase
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
@@ -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(),
);
$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('cache_warmer')
->will($this->returnValue($definition));
$container->expects($this->atLeastOnce())
->method('hasDefinition')
->with('cache_warmer')
->will($this->returnValue(true));
$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 @@ class AddCacheWarmerPassTest extends \PHPUnit_Framework_TestCase
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')
@@ -11,49 +11,52 @@
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
class AddConsoleCommandPassTest extends TestCase
{
public function testProcess()
/**
* @dataProvider visibilityProvider
*/
public function testProcess($public)
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddConsoleCommandPass());
$container->setParameter('my-command.class', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand');
$definition = new Definition('%my-command.class%');
$definition->setPublic($public);
$definition->addTag('console.command');
$container->setDefinition('my-command', $definition);
$container->compile();
$alias = 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand';
$this->assertTrue($container->hasAlias($alias));
$this->assertSame('my-command', (string) $container->getAlias($alias));
if ($container->hasAlias($alias)) {
$this->assertSame('my-command', (string) $container->getAlias($alias));
} else {
// 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('my-command'), $container->getParameter('console.command.ids'));
$this->assertSame(array($id), $container->getParameter('console.command.ids'));
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage The service "my-command" tagged "console.command" must be public.
*/
public function testProcessThrowAnExceptionIfTheServiceIsNotPublic()
public function visibilityProvider()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddConsoleCommandPass());
$definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand');
$definition->addTag('console.command');
$definition->setPublic(false);
$container->setDefinition('my-command', $definition);
$container->compile();
return array(
array(true),
array(false),
);
}
/**
@@ -88,26 +91,6 @@ class AddConsoleCommandPassTest extends \PHPUnit_Framework_TestCase
$container->compile();
}
public function testHttpKernelRegisterCommandsIngoreCommandAsAService()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddConsoleCommandPass());
$definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand');
$definition->addTag('console.command');
$container->setDefinition('my-command', $definition);
$container->compile();
$application = $this->getMock('Symfony\Component\Console\Application');
// Never called, because it's the
// Symfony\Bundle\FrameworkBundle\Console\Application that register
// commands as a service
$application->expects($this->never())->method('add');
$bundle = new ExtensionPresentBundle();
$bundle->setContainer($container);
$bundle->registerCommands($application);
}
}
class MyCommand extends Command
@@ -9,9 +9,12 @@
* 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;
class AddConstraintValidatorsPassTest extends \PHPUnit_Framework_TestCase
class AddConstraintValidatorsPassTest extends TestCase
{
public function testThatConstraintValidatorServicesAreProcessed()
{
@@ -20,14 +23,11 @@ class AddConstraintValidatorsPassTest extends \PHPUnit_Framework_TestCase
'my_constraint_validator_service2' => array(),
);
$validatorFactoryDefinition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
);
$validatorFactoryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock();
$validatorDefinition1 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass'));
$validatorDefinition2 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass'));
$validatorDefinition1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
$validatorDefinition2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
$validatorDefinition1->expects($this->atLeastOnce())
->method('getClass')
@@ -67,11 +67,8 @@ class AddConstraintValidatorsPassTest extends \PHPUnit_Framework_TestCase
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');

Some files were not shown because too many files have changed in this diff Show More