diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index afd31e75ec88b..e274617dcc465 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -34,6 +34,9 @@ FrameworkBundle --------------- * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass` has been deprecated. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass` class has been deprecated and will be removed in 4.0, use the + `Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass` class instead. HttpKernel ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index d88fc607d7a9b..98b62c9e6adb5 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -156,6 +156,9 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass` has been removed. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass` class has been removed, use the + `Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass` class instead. + SecurityBundle -------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 19f7da4d257be..989514ca4bafa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG is disabled. * Added `GlobalVariables::getToken()` * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. + * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass`. Use `Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass` instead. 3.2.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php index 046407351ceeb..3f36867757d73 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php @@ -11,48 +11,17 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass instead.', ProfilerPass::class), E_USER_DEPRECATED); + +use Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass as BaseProfilerPass; /** * Adds tagged data_collector services to profiler service. * + * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseProfilerPass} instead. + * * @author Fabien Potencier */ -class ProfilerPass implements CompilerPassInterface +class ProfilerPass extends BaseProfilerPass { - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition('profiler')) { - return; - } - - $definition = $container->getDefinition('profiler'); - - $collectors = new \SplPriorityQueue(); - $order = PHP_INT_MAX; - foreach ($container->findTaggedServiceIds('data_collector') as $id => $attributes) { - $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; - $template = null; - - 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)); - } - $template = array($attributes[0]['id'], $attributes[0]['template']); - } - - $collectors->insert(array($id, $template), array($priority, --$order)); - } - - $templates = array(); - foreach ($collectors as $collector) { - $definition->addMethodCall('add', array(new Reference($collector[0]))); - $templates[$collector[0]] = $collector[1]; - } - - $container->setParameter('data_collector.templates', $templates); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 535fa0a5b7caf..ab883a6759d7a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -22,7 +22,6 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RoutingResolverPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; @@ -36,6 +35,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ValidateWorkflowsPass; +use Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -74,7 +74,7 @@ public function build(ContainerBuilder $container) parent::build($container); $container->addCompilerPass(new RoutingResolverPass()); - $container->addCompilerPass(new ProfilerPass()); + $this->addCompilerPassIfExists($container, ProfilerPass::class); // must be registered before removing private services as some might be listeners/subscribers // but as late as possible to get resolved parameters $container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING); @@ -109,4 +109,11 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new CacheCollectorPass()); } } + + private function addCompilerPassIfExists(ContainerBuilder $container, $class, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, $priority = 0) + { + if (class_exists($class)) { + $container->addCompilerPass(new $class(), $type, $priority); + } + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php index 9edb44ebb6e1c..526d552167b6b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -14,6 +14,9 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; +/** + * @group legacy + */ class ProfilerPassTest extends \PHPUnit_Framework_TestCase { private $profilerDefinition; diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 8739a41da40a0..621c81945a98b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -50,6 +50,7 @@ "symfony/validator": "~3.2", "symfony/yaml": "~3.2", "symfony/property-info": "~2.8|~3.0", + "symfony/web-profiler-bundle": "~3.3", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", "twig/twig": "~1.26|~2.0" @@ -57,7 +58,8 @@ "conflict": { "phpdocumentor/reflection-docblock": "<3.0", "phpdocumentor/type-resolver": "<0.2.0", - "symfony/console": "<3.3" + "symfony/console": "<3.3", + "symfony/web-profiler-bundle": "<3.3" }, "suggest": { "ext-apcu": "For best performance of the system caches", diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 64102cc761c34..17945507c3a46 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.3.0 +----- + + * added `ProfilerPass` + 3.1.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Compiler/ProfilerPass.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Compiler/ProfilerPass.php new file mode 100644 index 0000000000000..c299c905b5c5a --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Compiler/ProfilerPass.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\WebProfilerBundle\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. + * + * @author Fabien Potencier + */ +class ProfilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (false === $container->hasDefinition('profiler')) { + return; + } + + $definition = $container->getDefinition('profiler'); + + $collectors = new \SplPriorityQueue(); + $order = PHP_INT_MAX; + foreach ($container->findTaggedServiceIds('data_collector') as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $template = null; + + 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)); + } + $template = array($attributes[0]['id'], $attributes[0]['template']); + } + + $collectors->insert(array($id, $template), array($priority, --$order)); + } + + $templates = array(); + foreach ($collectors as $collector) { + $definition->addMethodCall('add', array(new Reference($collector[0]))); + $templates[$collector[0]] = $collector[1]; + } + + $container->setParameter('data_collector.templates', $templates); + } +} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php new file mode 100644 index 0000000000000..7a7351e2e27cc --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\WebProfilerBundle\Tests\DependencyInjection\Compiler; + +use Symfony\Bundle\WebProfilerBundle\DependencyInjection\Compiler\ProfilerPass; +use Symfony\Component\DependencyInjection\Definition; + +class ProfilerPassTest extends \PHPUnit_Framework_TestCase +{ + private $profilerDefinition; + + protected function setUp() + { + $this->profilerDefinition = new Definition('ProfilerClass'); + } + + /** + * Tests that collectors that specify a template but no "id" will throw + * an exception (both are needed if the template is specified). + * + * Thus, a fully-valid tag looks something like this: + * + * + */ + public function testTemplateNoIdThrowsException() + { + // one service, with a template key, but no id + $services = array( + 'my_collector_service' => array(0 => array('template' => 'foo')), + ); + + $builder = $this->createContainerMock($services); + + $this->setExpectedException('InvalidArgumentException'); + + $profilerPass = new ProfilerPass(); + $profilerPass->process($builder); + } + + public function testValidCollector() + { + // one service, with a template key, but no id + $services = array( + 'my_collector_service' => array(0 => array('template' => 'foo', 'id' => 'my_collector')), + ); + + $container = $this->createContainerMock($services); + + // fake the getDefinition() to return a Profiler definition + $container->expects($this->atLeastOnce()) + ->method('getDefinition'); + + // assert that the data_collector.templates parameter should be set + $container->expects($this->once()) + ->method('setParameter') + ->with('data_collector.templates', array('my_collector_service' => array('my_collector', 'foo'))); + + $profilerPass = new ProfilerPass(); + $profilerPass->process($container); + + // grab the method calls off of the "profiler" definition + $methodCalls = $this->profilerDefinition->getMethodCalls(); + $this->assertCount(1, $methodCalls); + $this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call + } + + private function createContainerMock($services) + { + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter'))->getMock(); + $container->expects($this->any()) + ->method('hasDefinition') + ->with($this->equalTo('profiler')) + ->will($this->returnValue(true)); + $container->expects($this->any()) + ->method('getDefinition') + ->will($this->returnValue($this->profilerDefinition)); + $container->expects($this->atLeastOnce()) + ->method('findTaggedServiceIds') + ->will($this->returnValue($services)); + + return $container; + } +}