Files
profile/inc/sql_result.php

221 lines
9.0 KiB
PHP
Raw Normal View History

2026-03-09 20:51:08 +03:00
<?php
add_action('wp_footer', 'display_sql_queries_in_footer', 9999);
function display_sql_queries_in_footer() {
if (!current_user_can('administrator')) {
return;
}
global $wpdb;
if (empty($wpdb->queries)) {
echo '<div style="background: #fff; padding: 20px; margin: 20px; border: 1px solid #ccc; font-family: monospace; font-size: 14px; position: relative; z-index: 99999;">';
echo '<p>Нет данных о запросах. Убедитесь, что в wp-config.php добавлена строка:</p>';
echo '<code style="background: #f4f4f4; padding: 5px; display: block;">define( \'SAVEQUERIES\', true );</code>';
echo '</div>';
return;
}
$queries = $wpdb->queries;
$total_time = 0;
foreach ($queries as $query) {
$total_time += $query[1];
}
echo '<div id="sql-debug-panel" style="background: #fff; padding: 20px; margin: 20px; border: 1px solid #ccc; font-family: monospace; font-size: 14px; position: relative; z-index: 99999;">';
// Панель управления сортировкой
echo '<div style="margin-bottom: 20px; padding: 10px; background: #f5f5f5; border-radius: 5px;">';
echo '<h3 style="margin-top: 0; display: inline-block; margin-right: 20px;">SQL Запросы</h3>';
echo '<button onclick="sortQueries(\'time-desc\')" style="margin-right: 10px; padding: 5px 10px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer;">Самые медленные</button>';
echo '<button onclick="sortQueries(\'time-asc\')" style="margin-right: 10px; padding: 5px 10px; background: #27ae60; color: white; border: none; border-radius: 3px; cursor: pointer;">Самые быстрые</button>';
echo '<button onclick="sortQueries(\'default\')" style="margin-right: 10px; padding: 5px 10px; background: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer;">По умолчанию</button>';
echo '<span style="margin-left: 20px; font-weight: bold;">Всего запросов: ' . count($queries) . '</span>';
echo '</div>';
echo '<table id="sql-queries-table" style="width: 100%; border-collapse: collapse; margin-top: 15px;">';
echo '<thead>';
echo '<tr style="background: #2c3e50; color: #fff; cursor: pointer;">';
echo '<th style="padding: 8px; border: 1px solid #ddd; text-align: left;" onclick="sortQueries(\'time-desc\')">Время ⬇</th>';
echo '<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Запрос</th>';
echo '<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Вызвавший код</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
foreach ($queries as $query) {
$time = number_format($query[1] * 1000, 2);
$time_seconds = $query[1];
$color = '#27ae60';
if ($query[1] > 0.1) $color = '#f39c12';
if ($query[1] > 0.5) $color = '#e74c3c';
echo '<tr class="sql-query-row">';
echo '<td style="padding: 8px; border: 1px solid #ddd; color: ' . $color . '; font-weight: bold;" data-time="' . $time_seconds . '">' . $time . ' ms</td>';
echo '<td style="padding: 8px; border: 1px solid #ddd; word-break: break-all;">' . htmlspecialchars($query[0]) . '</td>';
echo '<td style="padding: 8px; border: 1px solid #ddd; font-size: 12px; color: #666;">' . $query[2] . '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
echo '<div style="margin-top: 15px; padding: 10px; background: #f8f9fa; border-left: 4px solid #3498db;">';
echo 'Общее время SQL запросов: <strong>' . number_format($total_time * 1000, 2) . ' ms</strong><br>';
echo 'Среднее время на запрос: <strong>' . number_format(($total_time / count($queries)) * 1000, 2) . ' ms</strong>';
echo '</div>';
echo '</div>';
// Добавляем JavaScript для сортировки
echo '
<script>
function sortQueries(sortType) {
const table = document.getElementById("sql-queries-table");
const tbody = table.querySelector("tbody");
const rows = Array.from(tbody.querySelectorAll("tr.sql-query-row"));
// Сбрасываем классы активной сортировки у заголовков
const headers = table.querySelectorAll("th");
headers.forEach(header => {
header.innerHTML = header.innerHTML.replace("", "").replace("", "");
});
// Добавляем индикатор сортировки
if (sortType === "time-desc") {
headers[0].innerHTML = "Время ⬇";
} else if (sortType === "time-asc") {
headers[0].innerHTML = "Время ⬆";
}
rows.sort((a, b) => {
const timeA = parseFloat(a.querySelector("td[data-time]").getAttribute("data-time"));
const timeB = parseFloat(b.querySelector("td[data-time]").getAttribute("data-time"));
switch(sortType) {
case "time-desc":
return timeB - timeA; // Самые медленные first
case "time-asc":
return timeA - timeB; // Самые быстрые first
case "default":
return 0; // Оригинальный порядок
default:
return 0;
}
});
// Очищаем и перезаполняем tbody
while (tbody.firstChild) {
tbody.removeChild(tbody.firstChild);
}
rows.forEach(row => {
tbody.appendChild(row);
});
}
// Добавляем поиск по запросам
function addSearchFeature() {
const panel = document.getElementById("sql-debug-panel");
const searchHtml = \`
<div style="margin-bottom: 15px;">
<input type="text" id="sql-search" placeholder="Поиск по запросам..."
style="padding: 8px; width: 300px; border: 1px solid #ddd; border-radius: 3px;">
<button onclick="filterQueries()" style="padding: 8px 15px; background: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer;">Поиск</button>
<button onclick="clearSearch()" style="padding: 8px 15px; background: #95a5a6; color: white; border: none; border-radius: 3px; cursor: pointer;">Очистить</button>
</div>
\`;
const controlsDiv = panel.querySelector("div");
controlsDiv.insertAdjacentHTML("afterend", searchHtml);
}
function filterQueries() {
const searchTerm = document.getElementById("sql-search").value.toLowerCase();
const rows = document.querySelectorAll("tr.sql-query-row");
rows.forEach(row => {
const queryText = row.querySelector("td:nth-child(2)").textContent.toLowerCase();
const callerText = row.querySelector("td:nth-child(3)").textContent.toLowerCase();
if (queryText.includes(searchTerm) || callerText.includes(searchTerm)) {
row.style.display = "";
} else {
row.style.display = "none";
}
});
}
function clearSearch() {
document.getElementById("sql-search").value = "";
const rows = document.querySelectorAll("tr.sql-query-row");
rows.forEach(row => {
row.style.display = "";
});
}
// Инициализируем поиск при загрузке
document.addEventListener("DOMContentLoaded", function() {
addSearchFeature();
});
</script>
';
}
// Добавляем стили и скрипты
add_action('wp_enqueue_scripts', 'add_sql_debug_styles');
function add_sql_debug_styles() {
if (!current_user_can('administrator')) {
return;
}
wp_enqueue_style('sql-debug-style', false);
echo '
<style>
#sql-debug-panel {
max-height: 600px;
overflow-y: auto;
position: fixed;
bottom: 20px;
right: 20px;
width: 90%;
max-width: 1200px;
box-shadow: 0 0 20px rgba(0,0,0,0.3);
border-radius: 8px;
}
.sql-query-row:hover {
background-color: #f8f9fa !important;
}
.sort-btn {
margin-right: 10px;
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
transition: background-color 0.3s;
}
.sort-btn:hover {
opacity: 0.9;
}
.sort-desc { background: #e74c3c; color: white; }
.sort-asc { background: #27ae60; color: white; }
.sort-default { background: #3498db; color: white; }
#sql-search {
padding: 8px;
width: 300px;
border: 1px solid #ddd;
border-radius: 4px;
margin-right: 10px;
}
</style>
';
}