Merge branch 'rhymix:master' into master

This commit is contained in:
Lastorder 2025-10-13 20:09:50 +09:00 committed by GitHub
commit a5c3dc8ae5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 219 additions and 95 deletions

View file

@ -1126,17 +1126,17 @@ class DB
}
else
{
$exceptions = [];
$exceptions = ['TABLE'];
}
// 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) {
return preg_replace_callback('/\b((?:DELETE\s+)?FROM|JOIN|INTO(?: TABLE)?|TABLE|(?<!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]);
return isset($m[2]) ? sprintf('`%s` AS `%s`', $m[1], $m[2]) : (ctype_upper($m[1]) ? $m[1] : sprintf('`%s`', $m[1]));
}
elseif ($type === 'FROM' || $type === 'JOIN')
{

View file

@ -70,8 +70,21 @@ class DBTableParser extends BaseParser
// Load columns.
foreach ($xml->column as $column_info)
{
// Is this column generated?
$is_generated = strval($column_info['generated'] ?? '') !== '';
if ($is_generated)
{
$column = new DBTable\GeneratedColumn;
$column->generated = strtolower($column_info['generated']);
$column->is_stored = strtolower($column_info['stored'] ?? '');
$column->is_stored = $column->is_stored !== 'virtual' && toBool($column->is_stored);
}
else
{
$column = new DBTable\Column;
}
// Get the column name and type.
$column = new DBTable\Column;
$column->name = strval($column_info['name']);
list($column->type, $column->xetype, $column->size) = self::getTypeAndSize(strval($column_info['type']), strval($column_info['size']));

View file

@ -398,7 +398,11 @@ class VariableBase
// Don't apply a filter if there is no variable.
$column = $this instanceof ColumnWrite ? $this->name : $this->column;
$filter = isset($this->filter) ? $this->filter : '';
if (!is_array($value) && strval($value) === '')
if (is_object($value) && !method_exists($value, '__toString'))
{
throw new \Rhymix\Framework\Exceptions\QueryError('Variable ' . $this->var . ' for column ' . $column . ' is not stringable');
}
if (is_scalar($value) && strval($value) === '')
{
$filter = '';
}

View file

@ -0,0 +1,12 @@
<?php
namespace Rhymix\Framework\Parsers\DBTable;
/**
* Generated column class.
*/
class GeneratedColumn extends Column
{
public $generated = 'always';
public $is_stored = false;
}

View file

@ -53,29 +53,42 @@ class Table
$columndef .= ' CHARACTER SET ' . $column->charset . ' COLLATE ' . $column->charset . '_general_ci';
}
}
if ($column instanceof GeneratedColumn)
{
$columndef .= ' GENERATED ' . strtoupper($column->generated ?: 'always');
$columndef .= ' AS (' . $column->default_value . ')';
if ($column->is_stored)
{
$columndef .= ' STORED';
}
}
else
{
if ($column->default_value !== null)
{
if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value))
{
$columndef .= ' DEFAULT ' . $column->default_value;
}
elseif (preg_match('/^\w+\(\)$/', $column->default_value))
{
$columndef .= ' DEFAULT ' . $column->default_value;
}
else
{
$columndef .= ' DEFAULT \'' . $column->default_value . '\'';
}
}
}
if ($column->not_null)
{
$columndef .= ' NOT NULL';
}
if ($column->default_value !== null)
{
if (preg_match('/(?:int|float|double|decimal|number)/i', $column->type) && is_numeric($column->default_value))
{
$columndef .= ' DEFAULT ' . $column->default_value;
}
elseif (preg_match('/^\w+\(\)$/', $column->default_value))
{
$columndef .= ' DEFAULT ' . $column->default_value;
}
else
{
$columndef .= ' DEFAULT \'' . $column->default_value . '\'';
}
}
if ($column->auto_increment)
{
$columndef .= ' AUTO_INCREMENT';
}
$columns[] = $columndef;
}

View file

@ -671,7 +671,7 @@ function utf8_mbencode($str): string
$bytes = array(ord($m[0][0]), ord($m[0][1]), ord($m[0][2]), ord($m[0][3]));
$codepoint = ((0x07 & $bytes[0]) << 18) + ((0x3F & $bytes[1]) << 12) + ((0x3F & $bytes[2]) << 6) + (0x3F & $bytes[3]);
return '&#x' . dechex($codepoint) . ';';
}, (string)$str);
}, (string)$str) ?? '';
}
/**
@ -686,11 +686,11 @@ function utf8_normalize_spaces($str, bool $multiline = false): string
{
if ($multiline)
{
return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str);
return preg_replace(['/((?!\x0A)[\pZ\pC])+/u', '/\x20*\x0A\x20*/'], [' ', "\n"], (string)$str) ?? '';
}
else
{
return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str);
return preg_replace('/[\pZ\pC]+/u', ' ', (string)$str) ?? '';
}
}

View file

@ -145,7 +145,7 @@
chunkfail: function(e, res) {
lastUploadTime = Date.now();
if (chunkStatus) {
alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "<br>\n" + res.errorThrown + "<br>\n" + res.textStatus);
alert(window.xe.lang.msg_file_upload_error + " (Type 3)" + "\n" + res.errorThrown + "\n" + res.textStatus);
return chunkStatus = false;
}
},
@ -169,7 +169,7 @@
result = jQuery.parseJSON(result);
}
if (!result) {
alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "<br>\n" + res.response().result);
alert(window.xe.lang.msg_file_upload_error + " (Type 5)" + "\n" + res.response().result);
return false;
}
@ -215,7 +215,7 @@
return false;
} else {
$container.data('editorStatus', null);
alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "<br>\n" + res.response().result);
alert(window.xe.lang.msg_file_upload_error + " (Type 6)" + "\n" + res.response().result);
return false;
}
},
@ -229,7 +229,7 @@
}
}, 1000);
if (chunkStatus) {
alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "<br>\n" + res.errorThrown + "<br>\n" + res.textStatus);
alert(window.xe.lang.msg_file_upload_error + " (Type 7)" + "\n" + res.errorThrown + "\n" + res.textStatus);
return false;
}
},

View file

@ -4,14 +4,18 @@
* This script runs the task queue.
*
* Unlike other scripts provided with Rhymix, it can be called
* both on the command line and over the network.
* both on the CLI (through index.php) and over the network (directly).
*/
define('RXQUEUE_CRON', true);
// If called on the CLI, run additional checks.
if (PHP_SAPI === 'cli')
{
require_once __DIR__ . '/common.php';
if (!defined('RX_VERSION'))
{
echo "Error: This script must not be called directly.\n";
exit(1);
}
}
else
{