diff --git a/src/Symfony/Framework/DoctrineBundle/DataCollector/DoctrineDataCollector.php b/src/Symfony/Framework/DoctrineBundle/DataCollector/DoctrineDataCollector.php
index 7b92cc968b..2d0639d23a 100644
--- a/src/Symfony/Framework/DoctrineBundle/DataCollector/DoctrineDataCollector.php
+++ b/src/Symfony/Framework/DoctrineBundle/DataCollector/DoctrineDataCollector.php
@@ -22,16 +22,24 @@ use Symfony\Framework\ProfilerBundle\DataCollector\DataCollector;
*/
class DoctrineDataCollector extends DataCollector
{
- protected function collect()
+ public function collect()
{
- $data = array();
+ $this->data = array();
if ($this->container->hasService('doctrine.dbal.logger')) {
- $data = array(
+ $this->data = array(
'queries' => $this->container->getDoctrine_Dbal_LoggerService()->queries,
);
}
+ }
- return $data;
+ public function getQueryCount()
+ {
+ return count($this->data['queries']);
+ }
+
+ public function getQueries()
+ {
+ return $this->data['queries'];
}
public function getSummary()
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/AppDataCollector.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/AppDataCollector.php
index 0013dca4ac..579595edfe 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/AppDataCollector.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/AppDataCollector.php
@@ -20,18 +20,28 @@ namespace Symfony\Framework\ProfilerBundle\DataCollector;
*/
class AppDataCollector extends DataCollector
{
- protected function collect()
+ public function collect()
{
$request = $this->container->getRequestService();
- return array(
+ $this->data = array(
'route' => $request->path->get('_route') ? $request->path->get('_route') : 'NONE',
'format' => $request->getRequestFormat(),
- 'content_type' => $this->manager->getResponse()->headers->get('Content-Type') ? $this->manager->getResponse()->headers->get('Content-Type') : 'text/html',
- 'code' => $this->manager->getResponse()->getStatusCode(),
+ 'content_type' => $this->profiler->getResponse()->headers->get('Content-Type') ? $this->profiler->getResponse()->headers->get('Content-Type') : 'text/html',
+ 'code' => $this->profiler->getResponse()->getStatusCode(),
);
}
+ public function getRoute()
+ {
+ return $this->data['route'];
+ }
+
+ public function getFormat()
+ {
+ return $this->data['format'];
+ }
+
public function getSummary()
{
return sprintf('
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/ConfigDataCollector.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/ConfigDataCollector.php
index a35132b6ad..e757750650 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/ConfigDataCollector.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/ConfigDataCollector.php
@@ -22,12 +22,12 @@ use Symfony\Foundation\Kernel;
*/
class ConfigDataCollector extends DataCollector
{
- protected function collect()
+ public function collect()
{
$kernel = $this->container->getKernelService();
- return array(
- 'token' => $this->manager->getProfilerStorage()->getToken(),
+ $this->data = array(
+ 'token' => $this->profiler->getProfilerStorage()->getToken(),
'symfony_version' => Kernel::VERSION,
'name' => $kernel->getName(),
'env' => $kernel->getEnvironment(),
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollector.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollector.php
index dccee57573..8771857c15 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollector.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollector.php
@@ -3,6 +3,7 @@
namespace Symfony\Framework\ProfilerBundle\DataCollector;
use Symfony\Components\DependencyInjection\ContainerInterface;
+use Symfony\Framework\ProfilerBundle\Profiler;
/*
* This file is part of the Symfony framework.
@@ -22,7 +23,7 @@ use Symfony\Components\DependencyInjection\ContainerInterface;
*/
abstract class DataCollector implements DataCollectorInterface
{
- protected $manager;
+ protected $profiler;
protected $container;
protected $data;
@@ -33,17 +34,18 @@ abstract class DataCollector implements DataCollectorInterface
public function getData()
{
- if (null === $this->data) {
- $this->data = $this->collect();
- }
-
return $this->data;
}
- abstract protected function collect();
-
- public function setCollectorManager(DataCollectorManager $manager)
+ public function setData($data)
{
- $this->manager = $manager;
+ $this->data = $data;
+ }
+
+ abstract public function collect();
+
+ public function setProfiler(Profiler $profiler)
+ {
+ $this->profiler = $profiler;
}
}
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorInterface.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorInterface.php
index 88b631b734..d3aa228258 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorInterface.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorInterface.php
@@ -2,6 +2,8 @@
namespace Symfony\Framework\ProfilerBundle\DataCollector;
+use Symfony\Framework\ProfilerBundle\Profiler;
+
/*
* This file is part of the Symfony framework.
*
@@ -20,7 +22,7 @@ namespace Symfony\Framework\ProfilerBundle\DataCollector;
*/
interface DataCollectorInterface
{
- public function setCollectorManager(DataCollectorManager $manager);
+ public function setProfiler(Profiler $profiler);
public function getData();
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorManager.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorManager.php
deleted file mode 100644
index 0c7270d139..0000000000
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/DataCollectorManager.php
+++ /dev/null
@@ -1,115 +0,0 @@
-
- *
- * This source file is subject to the MIT license that is bundled
- * with this source code in the file LICENSE.
- */
-
-/**
- * DataCollectorManager.
- *
- * @package Symfony
- * @subpackage Framework_ProfilerBundle
- * @author Fabien Potencier
- */
-class DataCollectorManager
-{
- protected $container;
- protected $profilerStorage;
- protected $collectors;
- protected $response;
- protected $lifetime;
- protected $logger;
-
- public function __construct(ContainerInterface $container, LoggerInterface $logger, ProfilerStorage $profilerStorage, $lifetime = 86400)
- {
- $this->container = $container;
- $this->logger = $logger;
- $this->lifetime = $lifetime;
- $this->profilerStorage = $profilerStorage;
- $this->collectors = $this->initCollectors();
- }
-
- /**
- * Registers a core.response listener.
- *
- * @param Symfony\Components\EventDispatcher\EventDispatcher $dispatcher An EventDispatcher instance
- */
- public function register(EventDispatcher $dispatcher)
- {
- $dispatcher->connect('core.response', array($this, 'handle'));
- }
-
- public function handle(Event $event, Response $response)
- {
- if (HttpKernelInterface::MASTER_REQUEST !== $event->getParameter('request_type')) {
- return $response;
- }
-
- $this->response = $response;
- $this->response->headers->set('X-Debug-Token', $this->profilerStorage->getToken());
-
- $data = array();
- foreach ($this->collectors as $name => $collector) {
- $data[$name] = $collector->getData();
- }
-
- try {
- $this->profilerStorage->write($data);
- $this->profilerStorage->purge($this->lifetime);
- } catch (\Exception $e) {
- $this->logger->err('Unable to store the profiler information.');
- }
-
- return $response;
- }
-
- public function getProfilerStorage()
- {
- return $this->profilerStorage;
- }
-
- public function getResponse()
- {
- return $this->response;
- }
-
- public function getCollectors()
- {
- return $this->collectors;
- }
-
- public function initCollectors()
- {
- $config = $this->container->findAnnotatedServiceIds('data_collector');
- $ids = array();
- $coreCollectors = array();
- $userCollectors = array();
- foreach ($config as $id => $attributes) {
- $collector = $this->container->getService($id);
- $collector->setCollectorManager($this);
-
- if (isset($attributes[0]['core']) && $attributes[0]['core']) {
- $coreCollectors[$collector->getName()] = $collector;
- } else {
- $userCollectors[$collector->getName()] = $collector;
- }
- }
-
- return $this->collectors = array_merge($coreCollectors, $userCollectors);
- }
-}
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/MemoryDataCollector.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/MemoryDataCollector.php
index 16c6755f07..3e64183b21 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/MemoryDataCollector.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/MemoryDataCollector.php
@@ -20,13 +20,18 @@ namespace Symfony\Framework\ProfilerBundle\DataCollector;
*/
class MemoryDataCollector extends DataCollector
{
- protected function collect()
+ public function collect()
{
- return array(
+ $this->data = array(
'memory' => memory_get_peak_usage(true),
);
}
+ public function getMemory()
+ {
+ return $this->data['memory'];
+ }
+
public function getSummary()
{
return sprintf('
diff --git a/src/Symfony/Framework/ProfilerBundle/DataCollector/TimerDataCollector.php b/src/Symfony/Framework/ProfilerBundle/DataCollector/TimerDataCollector.php
index 67cb7c5172..74a7c11ad1 100644
--- a/src/Symfony/Framework/ProfilerBundle/DataCollector/TimerDataCollector.php
+++ b/src/Symfony/Framework/ProfilerBundle/DataCollector/TimerDataCollector.php
@@ -20,13 +20,18 @@ namespace Symfony\Framework\ProfilerBundle\DataCollector;
*/
class TimerDataCollector extends DataCollector
{
- protected function collect()
+ public function collect()
{
- return array(
+ $this->data = array(
'time' => microtime(true) - $this->container->getKernelService()->getStartTime(),
);
}
+ public function getTime()
+ {
+ return $this->data['time'];
+ }
+
public function getSummary()
{
return sprintf('
diff --git a/src/Symfony/Framework/ProfilerBundle/DependencyInjection/ProfilerExtension.php b/src/Symfony/Framework/ProfilerBundle/DependencyInjection/ProfilerExtension.php
index c47295adc5..6e05139d0c 100644
--- a/src/Symfony/Framework/ProfilerBundle/DependencyInjection/ProfilerExtension.php
+++ b/src/Symfony/Framework/ProfilerBundle/DependencyInjection/ProfilerExtension.php
@@ -26,7 +26,7 @@ class ProfilerExtension extends LoaderExtension
{
public function configLoad($config, BuilderConfiguration $configuration)
{
- if (!$configuration->hasDefinition('data_collector_manager')) {
+ if (!$configuration->hasDefinition('profiler')) {
$loader = new XmlFileLoader(__DIR__.'/../Resources/config');
$configuration->merge($loader->load('collectors.xml'));
}
diff --git a/src/Symfony/Framework/ProfilerBundle/Listener/DataCollector.php b/src/Symfony/Framework/ProfilerBundle/Listener/DataCollector.php
new file mode 100644
index 0000000000..e9f5e9af15
--- /dev/null
+++ b/src/Symfony/Framework/ProfilerBundle/Listener/DataCollector.php
@@ -0,0 +1,56 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * DataCollector collects data for the current request by listening to the core.response event.
+ *
+ * @package Symfony
+ * @subpackage Framework_ProfilerBundle
+ * @author Fabien Potencier
+ */
+class DataCollector
+{
+ protected $profiler;
+
+ public function __construct(Profiler $profiler)
+ {
+ $this->profiler = $profiler;
+ }
+
+ /**
+ * Registers a core.response listener.
+ *
+ * @param Symfony\Components\EventDispatcher\EventDispatcher $dispatcher An EventDispatcher instance
+ */
+ public function register(EventDispatcher $dispatcher)
+ {
+ $dispatcher->connect('core.response', array($this, 'handle'));
+ }
+
+ public function handle(Event $event, Response $response)
+ {
+ if (HttpKernelInterface::MASTER_REQUEST !== $event->getParameter('request_type')) {
+ return $response;
+ }
+
+ $this->profiler->collect($response);
+
+ return $response;
+ }
+}
diff --git a/src/Symfony/Framework/ProfilerBundle/Listener/WebDebugToolbar.php b/src/Symfony/Framework/ProfilerBundle/Listener/WebDebugToolbar.php
index b894f09581..ecb52d1469 100644
--- a/src/Symfony/Framework/ProfilerBundle/Listener/WebDebugToolbar.php
+++ b/src/Symfony/Framework/ProfilerBundle/Listener/WebDebugToolbar.php
@@ -7,7 +7,7 @@ use Symfony\Components\EventDispatcher\EventDispatcher;
use Symfony\Components\EventDispatcher\Event;
use Symfony\Components\HttpKernel\Response;
use Symfony\Components\HttpKernel\HttpKernelInterface;
-use Symfony\Framework\ProfilerBundle\DataCollector\DataCollectorManager;
+use Symfony\Framework\ProfilerBundle\Profiler;
/*
* This file is part of the Symfony framework.
@@ -28,12 +28,12 @@ use Symfony\Framework\ProfilerBundle\DataCollector\DataCollectorManager;
class WebDebugToolbar
{
protected $container;
- protected $collectorManager;
+ protected $profiler;
- public function __construct(ContainerInterface $container, DataCollectorManager $collectorManager)
+ public function __construct(ContainerInterface $container, Profiler $profiler)
{
$this->container = $container;
- $this->collectorManager = $collectorManager;
+ $this->profiler = $profiler;
}
/**
@@ -77,7 +77,7 @@ class WebDebugToolbar
protected function injectToolbar(Response $response)
{
$data = '';
- foreach ($this->collectorManager->getCollectors() as $name => $collector) {
+ foreach ($this->profiler->getCollectors() as $name => $collector) {
$data .= $collector->getSummary();
}
diff --git a/src/Symfony/Framework/ProfilerBundle/Profiler.php b/src/Symfony/Framework/ProfilerBundle/Profiler.php
new file mode 100644
index 0000000000..689bf5a917
--- /dev/null
+++ b/src/Symfony/Framework/ProfilerBundle/Profiler.php
@@ -0,0 +1,192 @@
+
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Profiler.
+ *
+ * @package Symfony
+ * @subpackage Framework_ProfilerBundle
+ * @author Fabien Potencier
+ */
+class Profiler implements \ArrayAccess
+{
+ protected $container;
+ protected $profilerStorage;
+ protected $collectors;
+ protected $response;
+ protected $logger;
+
+ public function __construct(ContainerInterface $container, ProfilerStorage $profilerStorage, LoggerInterface $logger = null)
+ {
+ $this->container = $container;
+ $this->profilerStorage = $profilerStorage;
+ $this->logger = $logger;
+ $this->initCollectors();
+ $this->loadCollectorData();
+ }
+
+ public function __clone()
+ {
+ $this->profilerStorage = clone $this->profilerStorage;
+ }
+
+ public function load(Response $response)
+ {
+ return $this->getProfilerForToken($response->headers->get('X-Debug-Token'));
+ }
+
+ public function getProfilerForToken($token)
+ {
+ $profiler = clone $this;
+ $profiler->profilerStorage->setToken($token);
+ $profiler->loadCollectorData();
+
+ return $profiler;
+ }
+
+ public function collect(Response $response)
+ {
+ $this->response = $response;
+ $this->response->headers->set('X-Debug-Token', $this->profilerStorage->getToken());
+
+ $data = array();
+ foreach ($this->collectors as $name => $collector) {
+ $collector->collect();
+
+ $data[$name] = $collector->getData();
+ }
+
+ try {
+ $this->profilerStorage->write($data);
+ $this->profilerStorage->purge();
+ } catch (\Exception $e) {
+ if (null !== $this->logger) {
+ $this->logger->err('Unable to store the profiler information.');
+ }
+ }
+ }
+
+ public function getProfilerStorage()
+ {
+ return $this->profilerStorage;
+ }
+
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ public function loadCollectorData()
+ {
+ try {
+ foreach ($this->collectors as $name => $collector) {
+ $collector->setData($this->profilerStorage->getData($name));
+ }
+ } catch (\Exception $e) {
+ if (null !== $this->logger) {
+ $this->logger->err('Unable to read the profiler information.');
+ }
+ }
+ }
+
+ public function getCollectors()
+ {
+ return $this->collectors;
+ }
+
+ public function hasCollector($name)
+ {
+ return isset($this->collectors[$name]);
+ }
+
+ public function getCollector($name)
+ {
+ if (!isset($this->collectors[$name])) {
+ throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
+ }
+
+ return $this->collectors[$name];
+ }
+
+ /**
+ * Returns true if the named field exists.
+ *
+ * @param string $name The field name
+ *
+ * @param Boolean true if the field exists, false otherwise
+ */
+ public function offsetExists($name)
+ {
+ return $this->hasCollector($name);
+ }
+
+ /**
+ * Gets the value of a field.
+ *
+ * @param string $name The field name
+ *
+ * @throws \InvalidArgumentException if the field does not exist
+ */
+ public function offsetGet($name)
+ {
+ return $this->getCollector($name);
+ }
+
+ /**
+ * Sets the value of a field.
+ *
+ * @param string $name The field name
+ * @param string|array $value The value of the field
+ *
+ * @throws \InvalidArgumentException if the field does not exist
+ */
+ public function offsetSet($name, $value)
+ {
+ throw new \LogicException('The Collectors cannot be set.');
+ }
+
+ /**
+ * Unimplemented.
+ *
+ * @param string $name The field name
+ */
+ public function offsetUnset($name)
+ {
+ throw new \LogicException('The Collectors cannot be removed.');
+ }
+
+ protected function initCollectors()
+ {
+ $config = $this->container->findAnnotatedServiceIds('data_collector');
+ $ids = array();
+ $coreCollectors = array();
+ $userCollectors = array();
+ foreach ($config as $id => $attributes) {
+ $collector = $this->container->getService($id);
+ $collector->setProfiler($this);
+
+ if (isset($attributes[0]['core']) && $attributes[0]['core']) {
+ $coreCollectors[$collector->getName()] = $collector;
+ } else {
+ $userCollectors[$collector->getName()] = $collector;
+ }
+ }
+
+ $this->collectors = array_merge($coreCollectors, $userCollectors);
+ }
+}
diff --git a/src/Symfony/Framework/ProfilerBundle/ProfilerStorage.php b/src/Symfony/Framework/ProfilerBundle/ProfilerStorage.php
index efc986b313..6ef9f2c69b 100644
--- a/src/Symfony/Framework/ProfilerBundle/ProfilerStorage.php
+++ b/src/Symfony/Framework/ProfilerBundle/ProfilerStorage.php
@@ -23,12 +23,14 @@ class ProfilerStorage
protected $token;
protected $data;
protected $store;
+ protected $lifetime;
- public function __construct($store, $token = null)
+ public function __construct($store, $token = null, $lifetime = 86400)
{
$this->store = $store;
$this->token = null === $token ? uniqid() : $token;
$this->data = null;
+ $this->lifetime = (int) $lifetime;
}
public function hasData()
@@ -46,7 +48,13 @@ class ProfilerStorage
return $this->data;
}
- return isset($this->data[$name]) ? $this->data[$name] : null;
+ return isset($this->data[$name]) ? $this->data[$name] : array();
+ }
+
+ public function setToken($token)
+ {
+ $this->token = $token;
+ $this->data = null;
}
public function getToken()
@@ -134,10 +142,10 @@ class ProfilerStorage
}
}
- public function purge($lifetime)
+ public function purge()
{
$db = $this->initDb(false);
- $args = array(':time' => time() - (int) $lifetime);
+ $args = array(':time' => time() - $this->lifetime);
$this->exec($db, 'DELETE FROM data WHERE created_at < :time', $args);
$this->close($db);
}
diff --git a/src/Symfony/Framework/ProfilerBundle/Resources/config/collectors.xml b/src/Symfony/Framework/ProfilerBundle/Resources/config/collectors.xml
index fff25d9996..fc5fca3c64 100644
--- a/src/Symfony/Framework/ProfilerBundle/Resources/config/collectors.xml
+++ b/src/Symfony/Framework/ProfilerBundle/Resources/config/collectors.xml
@@ -5,10 +5,11 @@
xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd">
- Symfony\Framework\ProfilerBundle\DataCollector\DataCollectorManager
- Symfony\Framework\ProfilerBundle\ProfilerStorage
- %kernel.cache_dir%/profiler.db
- 86400
+ Symfony\Framework\ProfilerBundle\Profiler
+ Symfony\Framework\ProfilerBundle\ProfilerStorage
+ %kernel.cache_dir%/profiler.db
+ 86400
+ Symfony\Framework\ProfilerBundle\Listener\DataCollector
Symfony\Framework\ProfilerBundle\DataCollector\ConfigDataCollector
Symfony\Framework\ProfilerBundle\DataCollector\AppDataCollector
Symfony\Framework\ProfilerBundle\DataCollector\TimerDataCollector
@@ -16,16 +17,21 @@
-
-
+
-
-
- %data_collector_manager.lifetime%
+
+
-
- %data_collector_manager.storage.file%
+
+ %profiler.storage.file%
+ null
+ %profiler.storage.lifetime%
+
+
+
+
+
diff --git a/src/Symfony/Framework/ProfilerBundle/Resources/config/toolbar.xml b/src/Symfony/Framework/ProfilerBundle/Resources/config/toolbar.xml
index 64ae8a5019..1f50621ae1 100644
--- a/src/Symfony/Framework/ProfilerBundle/Resources/config/toolbar.xml
+++ b/src/Symfony/Framework/ProfilerBundle/Resources/config/toolbar.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/src/Symfony/Framework/ProfilerBundle/Tests/DependencyInjection/ProfilerExtensionTest.php b/src/Symfony/Framework/ProfilerBundle/Tests/DependencyInjection/ProfilerExtensionTest.php
index 5fe77d9e1b..ff3f3d77f9 100644
--- a/src/Symfony/Framework/ProfilerBundle/Tests/DependencyInjection/ProfilerExtensionTest.php
+++ b/src/Symfony/Framework/ProfilerBundle/Tests/DependencyInjection/ProfilerExtensionTest.php
@@ -23,7 +23,7 @@ class ProfilerExtensionTest extends TestCase
$loader = new ProfilerExtension();
$configuration = $loader->configLoad(array(), $configuration);
- $this->assertEquals('Symfony\\Framework\\ProfilerBundle\\DataCollector\\DataCollectorManager', $configuration->getParameter('data_collector_manager.class'), '->configLoad() loads the collectors.xml file if not already loaded');
+ $this->assertEquals('Symfony\\Framework\\ProfilerBundle\\Profiler', $configuration->getParameter('profiler.class'), '->configLoad() loads the collectors.xml file if not already loaded');
$this->assertFalse($configuration->hasParameter('debug.toolbar.class'), '->configLoad() does not load the toolbar.xml file');
$configuration = $loader->configLoad(array('toolbar' => true), $configuration);