diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml index a1c332a6ab..7d10cc70b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml @@ -9,6 +9,7 @@ Symfony\Component\Stopwatch\Stopwatch %kernel.cache_dir%/%kernel.container_class%.xml Symfony\Component\HttpKernel\Controller\TraceableControllerResolver + Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener @@ -26,5 +27,11 @@ + + + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig index 65d93a64d2..36a3fb0be2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig @@ -1,16 +1,30 @@ {% extends '@WebProfiler/Profiler/layout.html.twig' %} {% block toolbar %} - {% if collector.counterrors %} + {% if collector.counterrors or collector.countdeprecations %} {% set icon %} Logs - {{ collector.counterrors }} + {% if collector.counterrors %} + {% set statusColor = "red" %} + {% else %} + {% set statusColor = "yellow" %} + {% endif %} + {% set errorCount = collector.counterrors + collector.countdeprecations %} + {{ errorCount }} {% endset %} {% set text %} -
- Exception - {{ collector.counterrors }} -
+ {% if collector.counterrors %} +
+ Exception + {{ collector.counterrors }} +
+ {% endif %} + {% if collector.countdeprecations %} +
+ Deprecated Calls + {{ collector.countdeprecations }} +
+ {% endif %} {% endset %} {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %} {% endif %} @@ -20,9 +34,10 @@ Logger Logs - {% if collector.counterrors %} + {% if collector.counterrors or collector.countdeprecations %} + {% set errorCount = collector.counterrors + collector.countdeprecations %} - {{ collector.counterrors }} + {{ errorCount }} {% endif %} diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 97f7165303..629b451f70 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -38,8 +38,9 @@ class LoggerDataCollector extends DataCollector { if (null !== $this->logger) { $this->data = array( - 'error_count' => $this->logger->countErrors(), - 'logs' => $this->sanitizeLogs($this->logger->getLogs()), + 'error_count' => $this->logger->countErrors(), + 'logs' => $this->sanitizeLogs($this->logger->getLogs()), + 'deprecation_count' => $this->computeDeprecationCount() ); } } @@ -66,6 +67,11 @@ class LoggerDataCollector extends DataCollector return isset($this->data['logs']) ? $this->data['logs'] : array(); } + public function countDeprecations() + { + return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; + } + /** * {@inheritdoc} */ @@ -103,4 +109,16 @@ class LoggerDataCollector extends DataCollector return $context; } + + private function computeDeprecationCount() + { + $count = 0; + foreach ($this->logger->getLogs() as $log) { + if (isset($log['context']['type']) && 'deprecation' === $log['context']['type']) { + $count++; + } + } + + return $count; + } } diff --git a/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php b/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php index 605c08626c..d4bed00f43 100644 --- a/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php +++ b/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpKernel\Debug; +use Symfony\Component\HttpKernel\Log\LoggerInterface; + /** * ErrorHandler. * @@ -32,6 +34,9 @@ class ErrorHandler private $level; + /** @var LoggerInterface */ + private static $logger; + /** * Register the error handler. * @@ -54,6 +59,11 @@ class ErrorHandler $this->level = null === $level ? error_reporting() : $level; } + public static function setLogger(LoggerInterface $logger) + { + self::$logger = $logger; + } + /** * @throws \ErrorException When error_reporting returns error */ @@ -63,6 +73,14 @@ class ErrorHandler return false; } + if ($level & E_USER_DEPRECATED || $level & E_DEPRECATED) { + if (null !== self::$logger) { + self::$logger->warn($message, array('type' => 'deprecation', 'file' => $file, 'line' => $line)); + } + + return true; + } + if (error_reporting() & $level && $this->level & $level) { throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line); } diff --git a/src/Symfony/Component/HttpKernel/EventListener/DeprecationLoggerListener.php b/src/Symfony/Component/HttpKernel/EventListener/DeprecationLoggerListener.php new file mode 100644 index 0000000000..a40e866155 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/EventListener/DeprecationLoggerListener.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\HttpKernel\Log\LoggerInterface; +use Symfony\Component\HttpKernel\Debug\ErrorHandler; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Injects the logger into the ErrorHandler, so that it can log deprecation errors. + * + * @author Colin Frei + */ +class DeprecationLoggerListener implements EventSubscriberInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function injectLogger() + { + if (null !== $this->logger) { + ErrorHandler::setLogger($this->logger); + } + } + + public static function getSubscribedEvents() + { + return array(KernelEvents::REQUEST => 'injectLogger'); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php index a4b853c3ed..c4ec7634a4 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -27,18 +27,19 @@ class LoggerDataCollectorTest extends \PHPUnit_Framework_TestCase /** * @dataProvider getCollectTestData */ - public function testCollect($nb, $logs, $expected) + public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount) { $logger = $this->getMock('Symfony\Component\HttpKernel\Log\DebugLoggerInterface'); $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb)); - $logger->expects($this->once())->method('getLogs')->will($this->returnValue($logs)); + $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs)); $c = new LoggerDataCollector($logger); $c->collect(new Request(), new Response()); $this->assertSame('logger', $c->getName()); $this->assertSame($nb, $c->countErrors()); - $this->assertSame($expected ? $expected : $logs, $c->getLogs()); + $this->assertSame($expectedLogs ? $expectedLogs : $logs, $c->getLogs()); + $this->assertSame($expectedDeprecationCount, $c->countDeprecations()); } public function getCollectTestData() @@ -48,16 +49,28 @@ class LoggerDataCollectorTest extends \PHPUnit_Framework_TestCase 1, array(array('message' => 'foo', 'context' => array())), null, + 0 ), array( 1, array(array('message' => 'foo', 'context' => array('foo' => fopen(__FILE__, 'r')))), array(array('message' => 'foo', 'context' => array('foo' => 'Resource(stream)'))), + 0 ), array( 1, array(array('message' => 'foo', 'context' => array('foo' => new \stdClass()))), array(array('message' => 'foo', 'context' => array('foo' => 'Object(stdClass)'))), + 0 + ), + array( + 1, + array( + array('message' => 'foo', 'context' => array('type' => 'deprecation')), + array('message' => 'foo2', 'context' => array('type' => 'deprecation')) + ), + null, + 2 ), ); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php index 0eb2d79d4c..df1d23b53d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Debug/ErrorHandlerTest.php @@ -57,5 +57,27 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase } restore_error_handler(); + + $handler = ErrorHandler::register(E_USER_DEPRECATED); + $this->assertTrue($handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, 'foo')); + + restore_error_handler(); + + $handler = ErrorHandler::register(E_DEPRECATED); + $this->assertTrue($handler->handle(E_DEPRECATED, 'foo', 'foo.php', 12, 'foo')); + + restore_error_handler(); + + $logger = $this->getMock('Symfony\Component\HttpKernel\Log\LoggerInterface'); + $logger->expects($this->once())->method('warn')->with( + $this->equalTo('foo'), + $this->equalTo(array('type' => 'deprecation', 'file' => 'foo.php', 'line' => '12')) + ); + + $handler = ErrorHandler::register(E_USER_DEPRECATED); + $handler->setLogger($logger); + $handler->handle(E_USER_DEPRECATED, 'foo', 'foo.php', 12, 'foo'); + + restore_error_handler(); } } diff --git a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index e1a97654d6..bf502e8208 100644 --- a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -5,33 +5,43 @@ targetNamespace="http://symfony.com/schema/routing" elementFormDefault="qualified"> + + + + - + - - - - - - + + + + + + + - - + + + + + - - - - - + diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index e7a78ce6f0..1d6a109f07 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -195,6 +195,12 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface $this->logger->debug('Remember-me was requested; setting cookie.'); } + // Remove attribute from request that sets a NULL cookie. + // It was set by $this->cancelCookie() + // (cancelCookie does other things too for some RememberMeServices + // so we should still call it at the start of this method) + $request->attributes->remove(self::COOKIE_ATTR_NAME); + $this->onLoginSuccess($request, $response, $token); } diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index 2ad47f8c5e..9f4013d1b2 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -133,7 +133,6 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices ) ); - $request->attributes->remove(self::COOKIE_ATTR_NAME); $response->headers->setCookie( new Cookie( $this->options['name'],