2c766a4150562b473dde34c6eef08e3b237a511e
[yaffs-website] / web / modules / contrib / devel / webprofiler / src / DataCollector / DatabaseDataCollector.php
1 <?php
2
3 namespace Drupal\webprofiler\DataCollector;
4
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Database\Connection;
7 use Drupal\Core\Database\Database;
8 use Drupal\Core\StringTranslation\StringTranslationTrait;
9 use Drupal\webprofiler\DrupalDataCollectorInterface;
10 use Symfony\Component\HttpFoundation\Request;
11 use Symfony\Component\HttpFoundation\Response;
12 use Symfony\Component\HttpKernel\DataCollector\DataCollector;
13
14 /**
15  * Class DatabaseDataCollector
16  */
17 class DatabaseDataCollector extends DataCollector implements DrupalDataCollectorInterface {
18
19   use StringTranslationTrait, DrupalDataCollectorTrait;
20
21   /**
22    * @var \Drupal\Core\Database\Connection
23    */
24   private $database;
25
26   /**
27    * @var \Drupal\Core\Config\ConfigFactoryInterface
28    */
29   private $configFactory;
30
31   /**
32    * @param \Drupal\Core\Database\Connection $database
33    * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
34    */
35   public function __construct(Connection $database, ConfigFactoryInterface $configFactory) {
36     $this->database = $database;
37     $this->configFactory = $configFactory;
38   }
39
40   /**
41    * {@inheritdoc}
42    */
43   public function collect(Request $request, Response $response, \Exception $exception = NULL) {
44     $connections = [];
45     foreach (Database::getAllConnectionInfo() as $key => $info) {
46       $database = Database::getConnection('default', $key);
47       $connections[$key] = $database->getLogger()->get('webprofiler');
48     }
49
50     $this->data['connections'] = array_keys($connections);
51
52     $data = [];
53     foreach ($connections as $key => $queries) {
54       foreach ($queries as $query) {
55         // Remove caller args.
56         unset($query['caller']['args']);
57
58         // Remove query args element if empty.
59         if (isset($query['args']) && empty($query['args'])) {
60           unset($query['args']);
61         }
62
63         // Save time in milliseconds.
64         $query['time'] = $query['time'] * 1000;
65         $query['database'] = $key;
66         $data[] = $query;
67       }
68     }
69
70     $querySort = $this->configFactory->get('webprofiler.config')
71       ->get('query_sort');
72     if ('duration' === $querySort) {
73       usort(
74         $data, [
75           "Drupal\\webprofiler\\DataCollector\\DatabaseDataCollector",
76           "orderQueryByTime",
77         ]
78       );
79     }
80
81     $this->data['queries'] = $data;
82
83     $options = $this->database->getConnectionOptions();
84
85     // Remove password for security.
86     unset($options['password']);
87
88     $this->data['database'] = $options;
89   }
90
91   /**
92    * @return array
93    */
94   public function getDatabase() {
95     return $this->data['database'];
96   }
97
98   /**
99    * @return int
100    */
101   public function getQueryCount() {
102     return count($this->data['queries']);
103   }
104
105   /**
106    * @return array
107    */
108   public function getQueries() {
109     return $this->data['queries'];
110   }
111
112   /**
113    * Returns the total execution time.
114    *
115    * @return float
116    */
117   public function getTime() {
118     $time = 0;
119
120     foreach ($this->data['queries'] as $query) {
121       $time += $query['time'];
122     }
123
124     return $time;
125   }
126
127   /**
128    * Returns a color based on the number of executed queries.
129    *
130    * @return string
131    */
132   public function getColorCode() {
133     if ($this->getQueryCount() < 100) {
134       return 'green';
135     }
136     if ($this->getQueryCount() < 200) {
137       return 'yellow';
138     }
139
140     return 'red';
141   }
142
143   /**
144    * Returns the configured query highlight threshold.
145    *
146    * @return int
147    */
148   public function getQueryHighlightThreshold() {
149     // When a profile is loaded from storage this object is deserialized and
150     // no constructor is called so we cannot use dependency injection.
151     return \Drupal::config('webprofiler.config')->get('query_highlight');
152   }
153
154   /**
155    * {@inheritdoc}
156    */
157   public function getName() {
158     return 'database';
159   }
160
161   /**
162    * {@inheritdoc}
163    */
164   public function getTitle() {
165     return $this->t('Database');
166   }
167
168   /**
169    * {@inheritdoc}
170    */
171   public function getPanelSummary() {
172     return $this->t('Executed queries: @count', ['@count' => $this->getQueryCount()]);
173   }
174
175   /**
176    * {@inheritdoc}
177    */
178   public function getIcon() {
179     return 'iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAYAAABh2p9gAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQRJREFUeNpi/P//PwM1ARMDlcGogZQDlpMnT7pxc3NbA9nhQKxOpL5rQLwJiPeBsI6Ozl+YBOOOHTv+AOllQNwtLS39F2owKYZ/gRq8G4i3ggxEToggWzvc3d2Pk+1lNL4fFAs6ODi8JzdS7mMRVyDVoAMHDsANdAPiOCC+jCQvQKqBQB/BDbwBxK5AHA3E/kB8nKJkA8TMQBwLxaBIKQbi70AvTADSBiSadwFXpCikpKQU8PDwkGTaly9fHFigkaKIJid4584dkiMFFI6jkTJII0WVmpHCAixZQEXWYhDeuXMnyLsVlEQKI45qFBQZ8eRECi4DBaAlDqle/8A48ip6gAADANdQY88Uc0oGAAAAAElFTkSuQmCC';
180   }
181
182   /**
183    * {@inheritdoc}
184    */
185   public function getLibraries() {
186     return [
187       'webprofiler/database',
188     ];
189   }
190
191   /**
192    * {@inheritdoc}
193    */
194   public function getData() {
195     $data = $this->data;
196
197     $conn = Database::getConnection();
198     foreach ($data['queries'] as &$query) {
199       $explain = TRUE;
200       $type = 'select';
201
202       if (strpos($query['query'], 'INSERT') !== FALSE) {
203         $explain = FALSE;
204         $type = 'insert';
205       }
206
207       if (strpos($query['query'], 'UPDATE') !== FALSE) {
208         $explain = FALSE;
209         $type = 'update';
210       }
211
212       if (strpos($query['query'], 'CREATE') !== FALSE) {
213         $explain = FALSE;
214         $type = 'create';
215       }
216
217       if (strpos($query['query'], 'DELETE') !== FALSE) {
218         $explain = FALSE;
219         $type = 'delete';
220       }
221
222       $query['explain'] = $explain;
223       $query['type'] = $type;
224
225       $quoted = [];
226
227       if (isset($query['args'])) {
228         foreach ((array) $query['args'] as $key => $val) {
229           $quoted[$key] = is_null($val) ? 'NULL' : $conn->quote($val);
230         }
231       }
232
233       $query['query_args'] = strtr($query['query'], $quoted);
234     }
235
236     $data['query_highlight_threshold'] = $this->getQueryHighlightThreshold();
237
238     return $data;
239   }
240
241   /**
242    * @param $a
243    * @param $b
244    *
245    * @return int
246    */
247   private function orderQueryByTime($a, $b) {
248     $at = $a['time'];
249     $bt = $b['time'];
250
251     if ($at == $bt) {
252       return 0;
253     }
254     return ($at < $bt) ? 1 : -1;
255   }
256 }