mc-cms-namelessmc/core/classes/Database/QueryRecorder.php

123 lines
3.1 KiB
PHP
Raw Permalink Normal View History

2021-10-25 19:49:12 -07:00
<?php
/**
* Records PDO queries to display on exception page.
2021-10-25 19:49:12 -07:00
*
* @package NamelessMC\Database
* @see ErrorHandler
* @author Aberdeener
* @version 2.0.0-pr13
* @license MIT
2021-10-25 19:49:12 -07:00
*/
class QueryRecorder extends Instanceable
{
private array $_query_stack = [];
2021-10-25 19:49:12 -07:00
private int $_query_stack_num = 1;
2021-11-03 22:15:44 -07:00
/**
* Get an array of all the SQL queries that have been executed in this request.
*
* @return array SQL queries
*/
public function getSqlStack(): array
{
$stack = array_reverse($this->_query_stack);
// Compile queries - replace bound parameters with their values and syntax highlight
foreach ($stack as &$query) {
$query['sql_query'] = $this->compileQuery(
$query['sql_string'],
$query['sql_params']
);
}
return $stack;
2021-10-25 19:49:12 -07:00
}
2021-11-03 22:15:44 -07:00
/**
* Add a query to the stack.
*
* @param string $sql Raw SQL query executed
* @param array $params Bound parameters used in the query
2021-11-03 22:15:44 -07:00
*/
public function pushQuery(string $sql, array $params): void
{
if (!Debugging::canViewDetailedError()) {
return;
}
2021-11-03 22:15:44 -07:00
$backtrace = $this->lastReleventBacktrace();
2021-10-25 19:49:12 -07:00
$this->_query_stack[] = [
'number' => $this->_query_stack_num,
'frame' => ErrorHandler::parseFrame(null, $backtrace['file'], $backtrace['line'], $this->_query_stack_num),
'sql_string' => $sql,
'sql_params' => $params,
2021-10-25 19:49:12 -07:00
];
$this->_query_stack_num++;
}
2021-11-03 22:15:44 -07:00
/**
* Get the last debug_backtrace entry which is not the file that executed this query or a database class.
2021-11-03 22:15:44 -07:00
*
* @return array debug_backtrace entry
*/
private function lastReleventBacktrace(): array
{
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
2021-10-25 19:49:12 -07:00
$current_file = $last_file = $backtrace[0]['file'];
$i = 1;
while (
$current_file === $last_file
|| str_ends_with($backtrace[$i]['file'], 'DB.php')
) {
2021-10-25 19:49:12 -07:00
$last_file = $backtrace[$i]['file'];
$i++;
}
return $backtrace[$i];
}
2021-11-03 22:15:44 -07:00
/**
* Get a compiled SQL query with bound parameters replaced with their values
* and syntax highlighted.
*
* @param string $sql Raw SQL query
* @param array $params Bound parameters
2021-11-03 22:15:44 -07:00
* @return string Compiled + syntax highlighted SQL query
*/
private function compileQuery(string $sql, array $params): string
{
2021-10-25 19:49:12 -07:00
$comp = '';
$split = explode(' ?', $sql);
$i = 0;
foreach ($split as $section) {
if ($section == '') {
continue;
}
2021-11-16 15:53:28 -08:00
if (!isset($params[$i])) {
$comp .= $section;
$i++;
continue;
}
2021-10-25 19:49:12 -07:00
$param = $params[$i];
$comp .= "$section '$param'";
$i++;
}
if (!str_ends_with($comp, ';')) {
$comp .= ';';
}
2021-10-25 19:49:12 -07:00
2021-12-05 08:17:24 -08:00
return SqlFormatter::highlight(trim($comp));
2021-10-25 19:49:12 -07:00
}
2021-11-02 23:37:19 -07:00
}