Merge branch 'rhymix:master' into master

This commit is contained in:
Lastorder 2025-07-28 19:02:10 +09:00 committed by GitHub
commit 0598ae4b95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 132 additions and 63 deletions

View file

@ -3,7 +3,7 @@
/**
* RX_VERSION is the version number of the Rhymix CMS.
*/
define('RX_VERSION', '2.1.25');
define('RX_VERSION', '2.1.26');
/**
* RX_MICROTIME is the startup time of the current script, in microseconds since the Unix epoch.

View file

@ -1113,29 +1113,43 @@ class DB
*/
public function addPrefixes(string $query_string): string
{
// Return early if no prefix is set.
if (!$this->_prefix)
{
return $query_string;
}
// Generate a list of common table expressions (CTEs) to exclude from prefixing.
if (preg_match_all('/\bWITH(?:\s+RECURSIVE)?\s+`?(\w+)`?\s+AS\b/', $query_string, $matches))
{
$exceptions = $matches[1];
}
else
{
return preg_replace_callback('/((?:DELETE\s+)?FROM|JOIN|INTO|UPDATE)(?i)\s+((?:`?\w+\`?)(?:\s+AS\s+`?\w+`?)?(?:\s*,\s*(?:`?\w+\`?)(?:\s+AS\s+`?\w+`?)?)*)/', function($m) {
$type = strtoupper($m[1]);
$tables = array_map(function($str) use($type) {
return preg_replace_callback('/`?(\w+)`?(?:\s+AS\s+`?(\w+)`?)?/i', function($m) use($type) {
if ($type === 'FROM' || $type === 'JOIN')
{
return isset($m[2]) ? sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[2]) : sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[1]);
}
else
{
return isset($m[2]) ? sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[2]) : sprintf('`%s%s`', $this->_prefix, $m[1]);
}
}, trim($str));
}, explode(',', $m[2]));
return $m[1] . ' ' . implode(', ', $tables);
}, $query_string);
$exceptions = [];
}
// Add prefixes to all other table names in the query string.
return preg_replace_callback('/\b((?:DELETE\s+)?FROM|JOIN|INTO|(?<!KEY\s)UPDATE)(?i)\s+((?:`?\w+`?)(?:\s+AS\s+`?\w+`?)?(?:\s*,\s*(?:`?\w+\`?)(?:\s+AS\s+`?\w+`?)?)*)/', function($m) use($exceptions) {
$type = strtoupper($m[1]);
$tables = array_map(function($str) use($type, $exceptions) {
return preg_replace_callback('/`?(\w+)`?(?:\s+AS\s+`?(\w+)`?)?/i', function($m) use($type, $exceptions) {
if (count($exceptions) && in_array($m[1], $exceptions))
{
return isset($m[2]) ? sprintf('`%s` AS `%s`', $m[1], $m[2]) : sprintf('`%s`', $m[1]);
}
elseif ($type === 'FROM' || $type === 'JOIN')
{
return isset($m[2]) ? sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[2]) : sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[1]);
}
else
{
return isset($m[2]) ? sprintf('`%s%s` AS `%s`', $this->_prefix, $m[1], $m[2]) : sprintf('`%s%s`', $this->_prefix, $m[1]);
}
}, trim($str));
}, explode(',', $m[2]));
return $m[1] . ' ' . implode(', ', $tables);
}, $query_string);
}
/**
@ -1254,7 +1268,7 @@ class DB
if (isset($backtrace[$no]))
{
$result['called_method'] = ($backtrace[$no]['class'] ?? '') . ($backtrace[$no]['type'] ?? '') . ($backtrace[$no]['function'] ?? '');
$result['backtrace'] = $this->_debug_full_stack ? array_slice($backtrace, $no) : [];
$result['backtrace'] = $this->_debug_full_stack ? array_slice($backtrace, $no - 1) : [];
}
else
{

View file

@ -7,5 +7,27 @@ namespace Rhymix\Framework;
*/
class Exception extends \Exception
{
/**
* Get the file and line, skipping Rhymix framework files.
*
* This can be more helpful than just using getFile() and getLine()
* when the exception is thrown from a Rhymix framework file
* but the actual error is caused by a module or theme.
*
* @return string
*/
public function getUserFileAndLine(): string
{
$regexp = '!^' . preg_quote(\RX_BASEDIR, '!') . '(?:classes|common)/!';
$trace = $this->getTrace();
foreach ($trace as $frame)
{
if (!preg_match($regexp, $frame['file']))
{
return $frame['file'] . ':' . $frame['line'];
}
}
return $this->getFile() . ':' . $this->getLine();
}
}

View file

@ -148,7 +148,7 @@ $(function() {
if (data.queries[i].backtrace && data.queries[i].backtrace.length) {
backtrace = $('<ul></ul>').appendTo(description.find('li:first-child'));
for (j in data.queries[i].backtrace) {
if (data.queries[i].backtrace[j].file) {
if (j > 0 && data.queries[i].backtrace[j].file) {
backtrace.append($('<li></li>').text(data.queries[i].backtrace[j].file + ":" + data.queries[i].backtrace[j].line));
}
}

View file

@ -126,7 +126,7 @@ Database Queries
echo sprintf(' - Call Stack: %s', $query_caller) . ($query->count > 1 ? (' (×' . $query->count . ')') : '') . "\n";
foreach ($query->backtrace ?? [] as $key => $backtrace)
{
if (isset($backtrace['file']) && isset($backtrace['line']))
if ($key > 0 && isset($backtrace['file']) && isset($backtrace['line']))
{
echo sprintf(' %s line %d', $backtrace['file'], $backtrace['line']) . "\n";
}