Skip to content

Commit 687afd2

Browse files
author
jelte
committed
Convert Bundle & Bridge DataCollectors
1 parent e7bdab9 commit 687afd2

30 files changed

+845
-56
lines changed

src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
* DoctrineDataCollector.
2323
*
2424
* @author Fabien Potencier <fabien@symfony.com>
25+
*
26+
* @deprecated since 2.8, to be removed in 3.0. Use Symfony\Bridge\Twig\Profiler\DoctrineDataCollector instead.
2527
*/
2628
class DoctrineDataCollector extends DataCollector
2729
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Profiler;
13+
14+
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\DBAL\Logging\DebugStack;
16+
use Doctrine\DBAL\Types\Type;
17+
use Symfony\Component\Profiler\DataCollector\AbstractDataCollector;
18+
use Symfony\Component\Profiler\DataCollector\RuntimeDataCollectorInterface;
19+
20+
/**
21+
* DoctrineDataCollector.
22+
*
23+
* @author Fabien Potencier <fabien@symfony.com>
24+
*/
25+
class DoctrineDataCollector extends AbstractDataCollector implements RuntimeDataCollectorInterface
26+
{
27+
private $registry;
28+
private $connections;
29+
private $managers;
30+
private $loggers = array();
31+
32+
public function __construct(ManagerRegistry $registry)
33+
{
34+
$this->registry = $registry;
35+
$this->connections = $registry->getConnectionNames();
36+
$this->managers = $registry->getManagerNames();
37+
}
38+
39+
/**
40+
* Adds the stack logger for a connection.
41+
*
42+
* @param string $name
43+
* @param DebugStack $logger
44+
*/
45+
public function addLogger($name, DebugStack $logger)
46+
{
47+
$this->loggers[$name] = $logger;
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
public function collect()
54+
{
55+
$queries = array();
56+
foreach ($this->loggers as $name => $logger) {
57+
$queries[$name] = $this->sanitizeQueries($name, $logger->queries);
58+
}
59+
60+
return new DoctrineProfileData($queries, $this->registry->getConnections(), $this->registry->getManagers());
61+
}
62+
63+
/**
64+
* {@inheritdoc}
65+
*/
66+
public function getName()
67+
{
68+
return 'db';
69+
}
70+
71+
private function sanitizeQueries($connectionName, $queries)
72+
{
73+
foreach ($queries as $i => $query) {
74+
$queries[$i] = $this->sanitizeQuery($connectionName, $query);
75+
}
76+
77+
return $queries;
78+
}
79+
80+
private function sanitizeQuery($connectionName, $query)
81+
{
82+
$query['explainable'] = true;
83+
if (!is_array($query['params'])) {
84+
$query['params'] = array($query['params']);
85+
}
86+
foreach ($query['params'] as $j => $param) {
87+
if (isset($query['types'][$j])) {
88+
// Transform the param according to the type
89+
$type = $query['types'][$j];
90+
if (is_string($type)) {
91+
$type = Type::getType($type);
92+
}
93+
if ($type instanceof Type) {
94+
$query['types'][$j] = $type->getBindingType();
95+
$param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
96+
}
97+
}
98+
99+
list($query['params'][$j], $explainable) = $this->sanitizeParam($param);
100+
if (!$explainable) {
101+
$query['explainable'] = false;
102+
}
103+
}
104+
105+
return $query;
106+
}
107+
108+
/**
109+
* Sanitizes a param.
110+
*
111+
* The return value is an array with the sanitized value and a boolean
112+
* indicating if the original value was kept (allowing to use the sanitized
113+
* value to explain the query).
114+
*
115+
* @param mixed $var
116+
*
117+
* @return array
118+
*/
119+
private function sanitizeParam($var)
120+
{
121+
if (is_object($var)) {
122+
return array(sprintf('Object(%s)', get_class($var)), false);
123+
}
124+
125+
if (is_array($var)) {
126+
$a = array();
127+
$original = true;
128+
foreach ($var as $k => $v) {
129+
list($value, $orig) = $this->sanitizeParam($v);
130+
$original = $original && $orig;
131+
$a[$k] = $value;
132+
}
133+
134+
return array($a, $original);
135+
}
136+
137+
if (is_resource($var)) {
138+
return array(sprintf('Resource(%s)', get_resource_type($var)), false);
139+
}
140+
141+
return array($var, true);
142+
}
143+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Symfony\Bridge\Doctrine\Profiler;
4+
5+
use Symfony\Component\Profiler\ProfileData\ProfileDataInterface;
6+
7+
class DoctrineProfileData implements ProfileDataInterface
8+
{
9+
private $queries;
10+
private $connections;
11+
private $managers;
12+
13+
public function __construct(array $queries, array $connections, array $managers)
14+
{
15+
$this->queries = $queries;
16+
$this->connections = $connections;
17+
$this->managers = $managers;
18+
}
19+
20+
public function getManagers()
21+
{
22+
return $this->managers;
23+
}
24+
25+
public function getConnections()
26+
{
27+
return $this->connections;
28+
}
29+
30+
public function getQueryCount()
31+
{
32+
return array_sum(array_map('count', $this->queries));
33+
}
34+
35+
public function getQueries()
36+
{
37+
return $this->queries;
38+
}
39+
40+
public function getTime()
41+
{
42+
$time = 0;
43+
foreach ($this->queries as $queries) {
44+
foreach ($queries as $query) {
45+
$time += $query['executionMS'];
46+
}
47+
}
48+
49+
return $time;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Profiler;
13+
14+
use Doctrine\DBAL\Platforms\MySqlPlatform;
15+
use Symfony\Bridge\Doctrine\Profiler\DoctrineDataCollector;
16+
17+
class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
18+
{
19+
public function testCollectConnections()
20+
{
21+
$c = $this->createCollector(array());
22+
$data = $c->collect();
23+
$this->assertEquals(array('default' => 'doctrine.dbal.default_connection'), $data->getConnections());
24+
}
25+
26+
public function testCollectManagers()
27+
{
28+
$c = $this->createCollector(array());
29+
$data = $c->collect();
30+
$this->assertEquals(array('default' => 'doctrine.orm.default_entity_manager'), $data->getManagers());
31+
}
32+
33+
public function testCollectQueryCount()
34+
{
35+
$c = $this->createCollector(array());
36+
$data = $c->collect();
37+
$this->assertEquals(0, $data->getQueryCount());
38+
39+
$queries = array(
40+
array('sql' => 'SELECT * FROM table1', 'params' => array(), 'types' => array(), 'executionMS' => 0),
41+
);
42+
$c = $this->createCollector($queries);
43+
$data = $c->collect();
44+
$this->assertEquals(1, $data->getQueryCount());
45+
}
46+
47+
public function testCollectTime()
48+
{
49+
$c = $this->createCollector(array());
50+
$data = $c->collect();
51+
$this->assertEquals(0, $data->getTime());
52+
53+
$queries = array(
54+
array('sql' => 'SELECT * FROM table1', 'params' => array(), 'types' => array(), 'executionMS' => 1),
55+
);
56+
$c = $this->createCollector($queries);
57+
$data = $c->collect();
58+
$this->assertEquals(1, $data->getTime());
59+
60+
$queries = array(
61+
array('sql' => 'SELECT * FROM table1', 'params' => array(), 'types' => array(), 'executionMS' => 1),
62+
array('sql' => 'SELECT * FROM table2', 'params' => array(), 'types' => array(), 'executionMS' => 2),
63+
);
64+
$c = $this->createCollector($queries);
65+
$data = $c->collect();
66+
$this->assertEquals(3, $data->getTime());
67+
}
68+
69+
/**
70+
* @dataProvider paramProvider
71+
*/
72+
public function testCollectQueries($param, $types, $expected, $explainable)
73+
{
74+
$queries = array(
75+
array('sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => array($param), 'types' => $types, 'executionMS' => 1),
76+
);
77+
$c = $this->createCollector($queries);
78+
$data = $c->collect();
79+
80+
$collected_queries = $data->getQueries();
81+
$this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
82+
$this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
83+
}
84+
85+
/**
86+
* @dataProvider paramProvider
87+
*/
88+
public function testSerialization($param, $types, $expected, $explainable)
89+
{
90+
$queries = array(
91+
array('sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => array($param), 'types' => $types, 'executionMS' => 1),
92+
);
93+
$c = $this->createCollector($queries);
94+
$data = $c->collect();
95+
$data = unserialize(serialize($data));
96+
97+
$collected_queries = $data->getQueries();
98+
$this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
99+
$this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
100+
}
101+
102+
public function paramProvider()
103+
{
104+
return array(
105+
array('some value', array(), 'some value', true),
106+
array(1, array(), 1, true),
107+
array(true, array(), true, true),
108+
array(null, array(), null, true),
109+
array(new \DateTime('2011-09-11'), array('date'), '2011-09-11', true),
110+
array(fopen(__FILE__, 'r'), array(), 'Resource(stream)', false),
111+
array(new \SplFileInfo(__FILE__), array(), 'Object(SplFileInfo)', false),
112+
);
113+
}
114+
115+
private function createCollector($queries)
116+
{
117+
$connection = $this->getMockBuilder('Doctrine\DBAL\Connection')
118+
->disableOriginalConstructor()
119+
->getMock();
120+
$connection->expects($this->any())
121+
->method('getDatabasePlatform')
122+
->will($this->returnValue(new MySqlPlatform()));
123+
124+
$registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
125+
$registry
126+
->expects($this->any())
127+
->method('getConnectionNames')
128+
->will($this->returnValue(array('default' => 'doctrine.dbal.default_connection')));
129+
$registry
130+
->expects($this->any())
131+
->method('getManagerNames')
132+
->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager')));
133+
$registry->expects($this->any())
134+
->method('getConnection')
135+
->will($this->returnValue($connection));
136+
137+
$logger = $this->getMock('Doctrine\DBAL\Logging\DebugStack');
138+
$logger->queries = $queries;
139+
140+
$collector = new DoctrineDataCollector($registry);
141+
$collector->addLogger('default', $logger);
142+
143+
return $collector;
144+
}
145+
}

src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* TwigDataCollector.
2121
*
2222
* @author Fabien Potencier <fabien@symfony.com>
23+
*
24+
* @deprecated since 2.8, to be removed in 3.0. Use Symfony\Bridge\Twig\Profiler\TwigDataCollector instead.
2325
*/
2426
class TwigDataCollector extends DataCollector implements LateDataCollectorInterface
2527
{

0 commit comments

Comments
 (0)