Merge branch '4.0'

* 4.0:
  use brace-style regex delimiters
  Fixed typo RecursiveIterator -> RecursiveIteratorIterator
  [Cache] fix logic for fetching tag versions on TagAwareAdapter
  [FrameworkBundle] Remove dead code
  [FrameworkBundle] Use the correct service id for CachePoolPruneCommand in its compiler pass
  Hide short exception trace by default
  [Doctrine Bridge] fix priority for doctrine event listeners
  [Validator] make phpdoc of ObjectInitializerInterface interface more accurate
  [Validator] fixes phpdoc reference to an interface that was removed in Symfony 3.0
This commit is contained in:
Fabien Potencier 2018-05-07 09:14:12 +02:00
commit 8123bb102b
27 changed files with 279 additions and 160 deletions

View File

@ -11,22 +11,22 @@
namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers event listeners and subscribers to the available doctrine connections.
*
* @author Jeremy Mikola <jmikola@gmail.com>
* @author Alexander <iam.asm89@gmail.com>
* @author David Maicher <mail@dmaicher.de>
*/
class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
{
private $connections;
private $container;
private $eventManagers;
private $managerTemplate;
private $tagPrefix;
@ -53,97 +53,97 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
return;
}
$taggedSubscribers = $container->findTaggedServiceIds($this->tagPrefix.'.event_subscriber', true);
$taggedListeners = $container->findTaggedServiceIds($this->tagPrefix.'.event_listener', true);
if (empty($taggedSubscribers) && empty($taggedListeners)) {
return;
}
$this->container = $container;
$this->connections = $container->getParameter($this->connections);
$sortFunc = function ($a, $b) {
$a = isset($a['priority']) ? $a['priority'] : 0;
$b = isset($b['priority']) ? $b['priority'] : 0;
$this->addTaggedSubscribers($container);
$this->addTaggedListeners($container);
}
return $a > $b ? -1 : 1;
};
private function addTaggedSubscribers(ContainerBuilder $container)
{
$subscriberTag = $this->tagPrefix.'.event_subscriber';
$taggedSubscribers = $this->findAndSortTags($subscriberTag, $container);
if (!empty($taggedSubscribers)) {
$subscribersPerCon = $this->groupByConnection($taggedSubscribers);
foreach ($subscribersPerCon as $con => $subscribers) {
$em = $this->getEventManager($con);
uasort($subscribers, $sortFunc);
foreach ($subscribers as $id => $instance) {
$em->addMethodCall('addEventSubscriber', array(new Reference($id)));
foreach ($taggedSubscribers as $taggedSubscriber) {
list($id, $tag) = $taggedSubscriber;
$connections = isset($tag['connection']) ? array($tag['connection']) : array_keys($this->connections);
foreach ($connections as $con) {
if (!isset($this->connections[$con])) {
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $taggedSubscriber, implode(', ', array_keys($this->connections))));
}
}
}
if (!empty($taggedListeners)) {
$listenersPerCon = $this->groupByConnection($taggedListeners, true);
foreach ($listenersPerCon as $con => $listeners) {
$em = $this->getEventManager($con);
uasort($listeners, $sortFunc);
foreach ($listeners as $id => $instance) {
$em->addMethodCall('addEventListener', array(
array_unique($instance['event']),
isset($instance['lazy']) && $instance['lazy'] ? $id : new Reference($id),
));
}
$this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', array(new Reference($id)));
}
}
}
private function groupByConnection(array $services, $isListener = false)
private function addTaggedListeners(ContainerBuilder $container)
{
$grouped = array();
foreach ($allCons = array_keys($this->connections) as $con) {
$grouped[$con] = array();
}
$listenerTag = $this->tagPrefix.'.event_listener';
$taggedListeners = $this->findAndSortTags($listenerTag, $container);
foreach ($services as $id => $instances) {
foreach ($instances as $instance) {
if ($isListener) {
if (!isset($instance['event'])) {
throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
}
$instance['event'] = array($instance['event']);
foreach ($taggedListeners as $taggedListener) {
list($id, $tag) = $taggedListener;
$taggedListenerDef = $container->getDefinition($id);
if (!isset($tag['event'])) {
throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
}
if (!empty($instance['lazy'])) {
$this->container->getDefinition($id)->setPublic(true);
}
$connections = isset($tag['connection']) ? array($tag['connection']) : array_keys($this->connections);
foreach ($connections as $con) {
if (!isset($this->connections[$con])) {
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
}
$cons = isset($instance['connection']) ? array($instance['connection']) : $allCons;
foreach ($cons as $con) {
if (!isset($grouped[$con])) {
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
}
if ($isListener && isset($grouped[$con][$id])) {
$grouped[$con][$id]['event'] = array_merge($grouped[$con][$id]['event'], $instance['event']);
} else {
$grouped[$con][$id] = $instance;
}
if ($lazy = !empty($tag['lazy'])) {
$taggedListenerDef->setPublic(true);
}
// we add one call per event per service so we have the correct order
$this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array(array($tag['event']), $lazy ? $id : new Reference($id)));
}
}
return $grouped;
}
private function getEventManager($name)
private function getEventManagerDef(ContainerBuilder $container, $name)
{
if (null === $this->eventManagers) {
$this->eventManagers = array();
foreach ($this->connections as $n => $id) {
$this->eventManagers[$n] = $this->container->getDefinition(sprintf($this->managerTemplate, $n));
}
if (!isset($this->eventManagers[$name])) {
$this->eventManagers[$name] = $container->getDefinition(sprintf($this->managerTemplate, $name));
}
return $this->eventManagers[$name];
}
/**
* Finds and orders all service tags with the given name by their priority.
*
* The order of additions must be respected for services having the same priority,
* and knowing that the \SplPriorityQueue class does not respect the FIFO method,
* we should not use this class.
*
* @see https://bugs.php.net/bug.php?id=53710
* @see https://bugs.php.net/bug.php?id=60926
*
* @param string $tagName
* @param ContainerBuilder $container
*
* @return array
*/
private function findAndSortTags($tagName, ContainerBuilder $container)
{
$sortedTags = array();
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $tags) {
foreach ($tags as $attributes) {
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
$sortedTags[$priority][] = array($serviceId, $attributes);
}
}
if ($sortedTags) {
krsort($sortedTags);
$sortedTags = call_user_func_array('array_merge', $sortedTags);
}
return $sortedTags;
}
}

View File

@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
class RegisterEventListenersAndSubscribersPassTest extends TestCase
{
@ -56,12 +57,18 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase
$container
->register('a', 'stdClass')
->setPublic(false)
->addTag('doctrine.event_listener', array(
'event' => 'bar',
))
->addTag('doctrine.event_listener', array(
'event' => 'foo',
'priority' => -5,
))
->addTag('doctrine.event_listener', array(
'event' => 'bar',
'event' => 'foo_bar',
'priority' => 3,
'lazy' => true,
))
;
$container
@ -70,12 +77,34 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase
'event' => 'foo',
))
;
$container
->register('c', 'stdClass')
->addTag('doctrine.event_listener', array(
'event' => 'foo_bar',
'priority' => 4,
))
;
$this->process($container);
$this->assertEquals(array('b', 'a'), $this->getServiceOrder($container, 'addEventListener'));
$methodCalls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
$calls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
$this->assertEquals(array('foo', 'bar'), $calls[1][1][0]);
$this->assertEquals(
array(
array('addEventListener', array(array('foo_bar'), new Reference('c'))),
array('addEventListener', array(array('foo_bar'), new Reference('a'))),
array('addEventListener', array(array('bar'), new Reference('a'))),
array('addEventListener', array(array('foo'), new Reference('b'))),
array('addEventListener', array(array('foo'), new Reference('a'))),
),
$methodCalls
);
// not lazy so must be reference
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $methodCalls[0][1][1]);
// lazy so id instead of reference and must mark service public
$this->assertSame('a', $methodCalls[1][1][1]);
$this->assertTrue($container->getDefinition('a')->isPublic());
}
public function testProcessEventListenersWithMultipleConnections()
@ -88,15 +117,86 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase
'event' => 'onFlush',
))
;
$container
->register('b', 'stdClass')
->addTag('doctrine.event_listener', array(
'event' => 'onFlush',
'connection' => 'default',
))
;
$container
->register('c', 'stdClass')
->addTag('doctrine.event_listener', array(
'event' => 'onFlush',
'connection' => 'second',
))
;
$this->process($container);
$callsDefault = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
$this->assertEquals(
array(
array('addEventListener', array(array('onFlush'), new Reference('a'))),
array('addEventListener', array(array('onFlush'), new Reference('b'))),
),
$container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls()
);
$this->assertEquals('addEventListener', $callsDefault[0][0]);
$this->assertEquals(array('onFlush'), $callsDefault[0][1][0]);
$this->assertEquals(
array(
array('addEventListener', array(array('onFlush'), new Reference('a'))),
array('addEventListener', array(array('onFlush'), new Reference('c'))),
),
$container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls()
);
}
$callsSecond = $container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls();
$this->assertEquals($callsDefault, $callsSecond);
public function testProcessEventSubscribersWithMultipleConnections()
{
$container = $this->createBuilder(true);
$container
->register('a', 'stdClass')
->addTag('doctrine.event_subscriber', array(
'event' => 'onFlush',
))
;
$container
->register('b', 'stdClass')
->addTag('doctrine.event_subscriber', array(
'event' => 'onFlush',
'connection' => 'default',
))
;
$container
->register('c', 'stdClass')
->addTag('doctrine.event_subscriber', array(
'event' => 'onFlush',
'connection' => 'second',
))
;
$this->process($container);
$this->assertEquals(
array(
array('addEventSubscriber', array(new Reference('a'))),
array('addEventSubscriber', array(new Reference('b'))),
),
$container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls()
);
$this->assertEquals(
array(
array('addEventSubscriber', array(new Reference('a'))),
array('addEventSubscriber', array(new Reference('c'))),
),
$container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls()
);
}
public function testProcessEventSubscribersWithPriorities()
@ -133,11 +233,17 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase
;
$this->process($container);
$serviceOrder = $this->getServiceOrder($container, 'addEventSubscriber');
$unordered = array_splice($serviceOrder, 0, 3);
sort($unordered);
$this->assertEquals(array('c', 'd', 'e'), $unordered);
$this->assertEquals(array('b', 'a'), $serviceOrder);
$this->assertEquals(
array(
array('addEventSubscriber', array(new Reference('c'))),
array('addEventSubscriber', array(new Reference('d'))),
array('addEventSubscriber', array(new Reference('e'))),
array('addEventSubscriber', array(new Reference('b'))),
array('addEventSubscriber', array(new Reference('a'))),
),
$container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls()
);
}
public function testProcessNoTaggedServices()
@ -157,25 +263,6 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase
$pass->process($container);
}
private function getServiceOrder(ContainerBuilder $container, $method)
{
$order = array();
foreach ($container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls() as list($name, $arguments)) {
if ($method !== $name) {
continue;
}
if ('addEventListener' === $name) {
$order[] = (string) $arguments[1];
continue;
}
$order[] = (string) $arguments[0];
}
return $order;
}
private function createBuilder($multipleConnections = false)
{
$container = new ContainerBuilder();

View File

@ -12,6 +12,8 @@
namespace Symfony\Bridge\Twig\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -77,7 +79,7 @@ EOF
if (0 === count($filenames)) {
if (0 !== ftell(STDIN)) {
throw new \RuntimeException('Please provide a filename or pipe template content to STDIN.');
throw new RuntimeException('Please provide a filename or pipe template content to STDIN.');
}
$template = '';
@ -113,7 +115,7 @@ EOF
return Finder::create()->files()->in($filename)->name('*.twig');
}
throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename));
throw new RuntimeException(sprintf('File or directory "%s" is not readable', $filename));
}
private function validate($template, $file)
@ -142,7 +144,7 @@ EOF
case 'json':
return $this->displayJson($output, $files);
default:
throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Style\StyleInterface;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
@ -98,7 +99,7 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
$message .= sprintf("\n\nDid you mean \"%s\"?", $guess);
}
throw new \LogicException($message);
throw new LogicException($message);
}
public function validateConfiguration(ExtensionInterface $extension, $configuration)

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -95,7 +96,17 @@ EOT
$targetArg = $kernel->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg;
if (!is_dir($targetArg)) {
<<<<<<< HEAD
throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
=======
// deprecated, logic to be removed in 4.0
// this allows the commands to work out of the box with web/ and public/
if (is_dir(dirname($targetArg).'/web')) {
$targetArg = dirname($targetArg).'/web';
} else {
throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
}
>>>>>>> 3.4
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -84,7 +85,7 @@ EOF
$fs->remove($oldCacheDir);
if (!is_writable($realCacheDir)) {
throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
throw new RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
}
$io->comment(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
@ -77,7 +78,7 @@ EOF
} elseif ($pool instanceof Psr6CacheClearer) {
$clearers[$id] = $pool;
} else {
throw new \InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
throw new InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id));
}
}
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
@ -124,7 +125,7 @@ EOF
break;
default:
$io->writeln($message);
throw new \InvalidArgumentException('Only the yaml and xml formats are supported.');
throw new InvalidArgumentException('Only the yaml and xml formats are supported.');
}
$io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path));

View File

@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
@ -174,9 +175,9 @@ EOF
$name = $input->getArgument('name');
if ((null !== $name) && ($optionsCount > 0)) {
throw new \InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined with the service name argument.');
throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined with the service name argument.');
} elseif ((null === $name) && $optionsCount > 1) {
throw new \InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined together.');
throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined together.');
}
}
@ -215,7 +216,7 @@ EOF
$matchingServices = $this->findServiceIdsContaining($builder, $name);
if (empty($matchingServices)) {
throw new \InvalidArgumentException(sprintf('No services found that match "%s".', $name));
throw new InvalidArgumentException(sprintf('No services found that match "%s".', $name));
}
$default = 1 === count($matchingServices) ? $matchingServices[0] : null;

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -67,7 +68,7 @@ EOF
/**
* {@inheritdoc}
*
* @throws \InvalidArgumentException When route does not exist
* @throws InvalidArgumentException When route does not exist
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@ -84,7 +85,7 @@ EOF
}
if (!$route) {
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
throw new InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
}
$helper->describe($io, $route, array(

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
@ -151,7 +152,7 @@ EOF
$viewsPaths = array($input->getArgument('bundle').'/Resources/views');
if (!is_dir($transPaths[0])) {
throw new \InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
}
}
} elseif ($input->getOption('all')) {

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Translation\Catalogue\TargetOperation;
@ -151,7 +152,7 @@ EOF
$currentName = $transPaths[0];
if (!is_dir($transPaths[0])) {
throw new \InvalidArgumentException(sprintf('<error>"%s" is neither an enabled bundle nor a directory.</error>', $transPaths[0]));
throw new InvalidArgumentException(sprintf('<error>"%s" is neither an enabled bundle nor a directory.</error>', $transPaths[0]));
}
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -70,7 +71,7 @@ EOF
$workflow = $container->get('state_machine.'.$serviceId);
$type = 'state_machine';
} else {
throw new \InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $serviceId));
throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $serviceId));
}
if ('puml' === $input->getOption('dump-format')) {

View File

@ -11,7 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -27,7 +26,7 @@ class CachePoolPrunerPass implements CompilerPassInterface
private $cacheCommandServiceId;
private $cachePoolTag;
public function __construct(string $cacheCommandServiceId = CachePoolPruneCommand::class, string $cachePoolTag = 'cache.pool')
public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool')
{
$this->cacheCommandServiceId = $cacheCommandServiceId;
$this->cachePoolTag = $cachePoolTag;

View File

@ -108,11 +108,6 @@ class FrameworkExtension extends Extension
private $annotationsConfigEnabled = false;
private $validatorConfigEnabled = false;
/**
* @var string|null
*/
private $kernelRootHash;
/**
* Responds to the app.config configuration parameter.
*
@ -1572,20 +1567,6 @@ class FrameworkExtension extends Extension
}
}
/**
* Gets a hash of the kernel root directory.
*
* @return string
*/
private function getKernelRootHash(ContainerBuilder $container)
{
if (!$this->kernelRootHash) {
$this->kernelRootHash = hash('sha256', $container->getParameter('kernel.root_dir'));
}
return $this->kernelRootHash;
}
/**
* Returns the base path for the XSD files.
*

View File

@ -12,7 +12,6 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
@ -25,7 +24,7 @@ class CachePoolPrunerPassTest extends TestCase
public function testCompilerPassReplacesCommandArgument()
{
$container = new ContainerBuilder();
$container->register(CachePoolPruneCommand::class)->addArgument(array());
$container->register('console.command.cache_pool_prune')->addArgument(array());
$container->register('pool.foo', FilesystemAdapter::class)->addTag('cache.pool');
$container->register('pool.bar', PhpFilesAdapter::class)->addTag('cache.pool');
@ -36,7 +35,7 @@ class CachePoolPrunerPassTest extends TestCase
'pool.foo' => new Reference('pool.foo'),
'pool.bar' => new Reference('pool.bar'),
);
$argument = $container->getDefinition(CachePoolPruneCommand::class)->getArgument(0);
$argument = $container->getDefinition('console.command.cache_pool_prune')->getArgument(0);
$this->assertInstanceOf(IteratorArgument::class, $argument);
$this->assertEquals($expected, $argument->getValues());
@ -64,7 +63,7 @@ class CachePoolPrunerPassTest extends TestCase
public function testCompilerPassThrowsOnInvalidDefinitionClass()
{
$container = new ContainerBuilder();
$container->register(CachePoolPruneCommand::class)->addArgument(array());
$container->register('console.command.cache_pool_prune')->addArgument(array());
$container->register('pool.not-found', NotFound::class)->addTag('cache.pool');
$pass = new CachePoolPrunerPass();

View File

@ -12,6 +12,8 @@
namespace Symfony\Bundle\SecurityBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@ -171,7 +173,7 @@ EOF
return $passwordQuestion->setValidator(function ($value) {
if ('' === trim($value)) {
throw new \Exception('The password must not be empty.');
throw new InvalidArgumentException('The password must not be empty.');
}
return $value;
@ -190,7 +192,16 @@ EOF
}
if (empty($this->userClasses)) {
<<<<<<< HEAD
throw new \RuntimeException('There are no configured encoders for the "security" extension.');
=======
if (null === $this->encoderFactory) {
// BC to be removed and simply keep the exception whenever there is no configured user classes in 4.0
return User::class;
}
throw new RuntimeException('There are no configured encoders for the "security" extension.');
>>>>>>> 3.4
}
if (!$input->isInteractive() || 1 === count($this->userClasses)) {

View File

@ -15,6 +15,8 @@ use Monolog\Formatter\FormatterInterface;
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -78,7 +80,7 @@ EOF
$filter = $input->getOption('filter');
if ($filter) {
if (!class_exists(ExpressionLanguage::class)) {
throw new \LogicException('Package "symfony/expression-language" is required to use the "filter" option.');
throw new LogicException('Package "symfony/expression-language" is required to use the "filter" option.');
}
$this->el = new ExpressionLanguage();
}
@ -97,7 +99,7 @@ EOF
}
if (!$socket = stream_socket_server($host, $errno, $errstr)) {
throw new \RuntimeException(sprintf('Server start failed on "%s": %s %s.', $host, $errstr, $errno));
throw new RuntimeException(sprintf('Server start failed on "%s": %s %s.', $host, $errstr, $errno));
}
foreach ($this->getLogs($socket) as $clientId => $message) {

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\WebServerBundle\Command;
use Symfony\Bundle\WebServerBundle\WebServer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -74,7 +75,7 @@ EOF
} elseif ('port' === $filter) {
$output->write($port);
} else {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid filter.', $filter));
throw new InvalidArgumentException(sprintf('"%s" is not a valid filter.', $filter));
}
} else {
return 1;

View File

@ -345,6 +345,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R
foreach ($tagVersions as $tag => $version) {
$tags[$tag.static::TAGS_PREFIX] = $tag;
if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) {
$fetchTagVersions = true;
continue;
}
$version -= $this->knownTagVersions[$tag][1];

View File

@ -69,6 +69,12 @@ class TagAwareAdapterTest extends AdapterTestCase
$this->assertFalse($pool->getItem('i1')->isHit());
$this->assertFalse($pool->getItem('i3')->isHit());
$this->assertTrue($pool->getItem('foo')->isHit());
$anotherPoolInstance = $this->createCachePool();
$this->assertFalse($anotherPoolInstance->getItem('i1')->isHit());
$this->assertFalse($anotherPoolInstance->getItem('i3')->isHit());
$this->assertTrue($anotherPoolInstance->getItem('foo')->isHit());
}
public function testInvalidateCommits()

View File

@ -17,7 +17,7 @@ namespace Symfony\Component\Form\Util;
* Contrary to \ArrayIterator, this iterator recognizes changes in the original
* array during iteration.
*
* You can wrap the iterator into a {@link \RecursiveIterator} in order to
* You can wrap the iterator into a {@link \RecursiveIteratorIterator} in order to
* enter any child form that inherits its parent's data and iterate the children
* of that form as well.
*

View File

@ -597,7 +597,7 @@ class Request
public static function setTrustedHosts(array $hostPatterns)
{
self::$trustedHostPatterns = array_map(function ($hostPattern) {
return sprintf('#%s#i', $hostPattern);
return sprintf('{%s}i', $hostPattern);
}, $hostPatterns);
// we need to reset trusted hosts on trusted host patterns change
self::$trustedHosts = array();

View File

@ -23,6 +23,7 @@ class RequestTest extends TestCase
{
// reset
Request::setTrustedProxies(array(), -1);
Request::setTrustedHosts(array());
}
public function testInitialize()
@ -1939,9 +1940,15 @@ class RequestTest extends TestCase
$request->headers->set('host', 'subdomain.trusted.com');
$this->assertEquals('subdomain.trusted.com', $request->getHost());
}
// reset request for following tests
Request::setTrustedHosts(array());
public function testSetTrustedHostsDoesNotBreakOnSpecialCharacters()
{
Request::setTrustedHosts(array('localhost(\.local){0,1}#,example.com', 'localhost'));
$request = Request::create('/');
$request->headers->set('host', 'localhost');
$this->assertSame('localhost', $request->getHost());
}
public function testFactory()

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Translation\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -81,14 +82,14 @@ EOF
if (!$filename) {
if (!$stdin = $this->getStdin()) {
throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.');
throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
}
return $this->display($io, array($this->validate($stdin)));
}
if (!$this->isReadable($filename)) {
throw new \RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
}
$filesInfo = array();
@ -149,7 +150,7 @@ EOF
case 'json':
return $this->displayJson($io, $files);
default:
throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
}
}

View File

@ -14,7 +14,7 @@ namespace Symfony\Component\Validator;
/**
* Prepares an object for validation.
*
* Concrete implementations of this interface are used by {@link ValidationVisitorInterface}
* Concrete implementations of this interface are used by {@link Validator\ContextualValidatorInterface}
* to initialize objects just before validating them.
*
* @author Fabien Potencier <fabien@symfony.com>

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\Yaml\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -86,14 +88,14 @@ EOF
if (!$filename) {
if (!$stdin = $this->getStdin()) {
throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.');
throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
}
return $this->display($io, array($this->validate($stdin, $flags)));
}
if (!$this->isReadable($filename)) {
throw new \RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
}
$filesInfo = array();
@ -133,7 +135,7 @@ EOF
case 'json':
return $this->displayJson($io, $files);
default:
throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
}
}