Compare commits

...

20 commits

Author SHA1 Message Date
Lastorder
a5c3dc8ae5
Merge branch 'rhymix:master' into master 2025-10-13 20:09:50 +09:00
Kijin Sung
8671c058d5 Fix incorrect page range when there are not enough pages #2602 2025-09-30 22:45:28 +09:00
Kijin Sung
32c9c91b82 Fix stretching of image on mobile 2025-09-30 22:35:10 +09:00
Kijin Sung
653ca4f697 Add "TABLE" to list of keywords to recognize in addPrefixes() 2025-09-30 22:27:36 +09:00
Kijin Sung
5dcc0f92a4 Fix incorrect request_uri and other JS variables if accessed on an unconfigured domain 2025-09-30 22:16:35 +09:00
Kijin Sung
4869d4384d Remove unnecessary <br> tag from uploader error messages 2025-09-30 22:07:57 +09:00
Kijin Sung
847415f1af Fix warning when domain is not given 2025-09-30 20:49:40 +09:00
Kijin Sung
16b6544f9d Fix null return value when regexp replace fails on invalid input 2025-09-20 11:34:54 +09:00
Kijin Sung
dcd84033cf Set default layout_file depending on the current layout_path 2025-09-18 19:39:37 +09:00
Kijin Sung
61ea93064a Remove deprecated exec_xml() from signup value check function 2025-09-16 20:33:54 +09:00
Kijin Sung
6d25f663b1 Fix double escape of summary in RSS 2025-09-16 14:35:47 +09:00
Kijin Sung
5d52df9c9a Use empty() instead of simple ! to check superglobals 2025-09-16 14:26:34 +09:00
Kijin Sung
146ff27801 Fix error when editing a domain whose index module has been deleted 2025-09-15 00:34:38 +09:00
Kijin Sung
60552ba96b Throw error in filterValue() if an unstringable object is given 2025-09-15 00:30:00 +09:00
Kijin Sung
85be8b7669 Fix fatal error if getUnlinkedMenu() fails during module insert 2025-09-15 00:27:41 +09:00
Kijin Sung
c3102da73f Fix #2600 misplaced decoding line 2025-09-10 07:42:38 +09:00
Kijin Sung
40067c0b53 Support generated columns #2596 2025-09-09 17:18:31 +09:00
Kijin Sung
5e4b48f19b Prevent direct access to cron.php on CLI 2025-09-09 15:30:29 +09:00
Kijin Sung
9734473b49 Initialize $_SESSION to an empty array even in CLI, to prevent spurious warnings later on 2025-09-09 15:25:24 +09:00
Kijin Sung
3c3e510c2e Fix double escaping of document and comment summary 2025-09-09 15:24:54 +09:00
24 changed files with 219 additions and 95 deletions

View file

@ -25,7 +25,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// CSS selector for photoswipe items. // CSS selector for photoswipe items.
var ps_find_selector = 'img:not(' + ps_skip_elements + ps_skip_class + '), img' + ps_enroll_class; var ps_find_selector = 'img:not(' + ps_skip_elements + ps_skip_class + '), img' + ps_enroll_class;
// parse slide data (url, title, size ...) from DOM elements // parse slide data (url, title, size ...) from DOM elements
// (children of gallerySelector) // (children of gallerySelector)
var parseThumbnailElements = function(el) { var parseThumbnailElements = function(el) {
var imgElements = $(el).find(ps_find_selector), var imgElements = $(el).find(ps_find_selector),
@ -39,7 +39,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
imgEl = imgElements.get(i); // <img> element imgEl = imgElements.get(i); // <img> element
// include only element nodes // include only element nodes
if (imgEl.nodeType !== 1 || !imgEl.src || !$(imgEl).attr('data-pswp-pid')) { if (imgEl.nodeType !== 1 || !imgEl.src || !$(imgEl).attr('data-pswp-pid')) {
continue; continue;
} }
@ -56,11 +56,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
var ps_skip_alt_class = '.photoswipe-no-caption'; var ps_skip_alt_class = '.photoswipe-no-caption';
if(imgEl.alt && !$(imgEl).is(ps_skip_alt_class)) { if(imgEl.alt && !$(imgEl).is(ps_skip_alt_class)) {
item.title = imgEl.alt; item.title = imgEl.alt;
} }
if(imgEl.title && !$(imgEl).is(ps_skip_alt_class)) { if(imgEl.title && !$(imgEl).is(ps_skip_alt_class)) {
item.title = imgEl.title; item.title = imgEl.title;
} }
item.el = imgEl; // save link to element for getThumbBoundsFn item.el = imgEl; // save link to element for getThumbBoundsFn
@ -87,7 +87,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
if(!clickedListItem) { if(!clickedListItem) {
return; return;
} }
e = e || window.event; e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false; e.preventDefault ? e.preventDefault() : e.returnValue = false;
@ -108,8 +108,8 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
}*/ }*/
for (var i = 0; i < numChildNodes; i++) { for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) { if(childNodes[i].nodeType !== 1 || !$(childNodes[i]).attr('data-pswp-pid')) {
continue; continue;
} }
if(childNodes[i] === clickedListItem) { if(childNodes[i] === clickedListItem) {
@ -140,7 +140,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
if(!vars[i]) { if(!vars[i]) {
continue; continue;
} }
var pair = vars[i].split('='); var pair = vars[i].split('=');
if(pair.length < 2) { if(pair.length < 2) {
continue; continue;
} }
@ -172,7 +172,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// See Options -> getThumbBoundsFn section of documentation for more info // See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el, var thumbnail = items[index].el,
pageYScroll = window.pageYOffset || document.documentElement.scrollTop, pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect(); rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width}; return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}, },
@ -191,7 +191,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
// PhotoSwipe opened from URL // PhotoSwipe opened from URL
if(fromURL) { if(fromURL) {
if(options.galleryPIDs) { if(options.galleryPIDs) {
// parse real index when custom PIDs are used // parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url // http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) { for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) { if(items[j].pid == index) {
@ -232,6 +232,7 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
var regx_skip = /(?:(modules|addons|classes|common|layouts|libs|widgets|widgetstyles)\/)/i; var regx_skip = /(?:(modules|addons|classes|common|layouts|libs|widgets|widgetstyles)\/)/i;
var regx_allow_i6pngfix = /(?:common\/tpl\/images\/blank\.gif$)/i; var regx_allow_i6pngfix = /(?:common\/tpl\/images\/blank\.gif$)/i;
var isMobile = String(navigator.userAgent).match(/mobile/i);
var galleryImgEls = $(galleryElements[i]).find(ps_find_selector); var galleryImgEls = $(galleryElements[i]).find(ps_find_selector);
for(var j = 0, jl = galleryImgEls.length; j < jl; j++) { for(var j = 0, jl = galleryImgEls.length; j < jl; j++) {
// skip components // skip components
@ -240,6 +241,11 @@ var initPhotoSwipeFromDOM = function(gallerySelector) {
//$(galleryImgEls[j]).attr('data-pswp-uid', i+1); //$(galleryImgEls[j]).attr('data-pswp-uid', i+1);
$(galleryImgEls[j]).attr('data-pswp-pid', j+1); $(galleryImgEls[j]).attr('data-pswp-pid', j+1);
// Fix stretching of image on mobile
if (isMobile) {
galleryImgEls[j].style.height = 'auto';
galleryImgEls[j].height = null;
}
} }
} }

View file

@ -338,7 +338,11 @@ class Context
} }
// start session // start session
if (\PHP_SAPI !== 'cli') if (\PHP_SAPI === 'cli')
{
$_SESSION = [];
}
else
{ {
if (self::$_current_request->getRouteOption('enable_session')) if (self::$_current_request->getRouteOption('enable_session'))
{ {
@ -1214,7 +1218,7 @@ class Context
else else
{ {
// Set HTTP_RAW_POST_DATA for third-party apps that look for it. // Set HTTP_RAW_POST_DATA for third-party apps that look for it.
if (!$_POST && !isset($GLOBALS['HTTP_RAW_POST_DATA'])) if (empty($_POST) && empty($_FILES) && !isset($GLOBALS['HTTP_RAW_POST_DATA']))
{ {
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input'); $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');
} }
@ -1230,7 +1234,7 @@ class Context
} }
// Decide whether it's JSON or XMLRPC by looking at the first character of the POST data. // Decide whether it's JSON or XMLRPC by looking at the first character of the POST data.
if (!$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) if (empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
{ {
self::$_instance->request_method = substr($GLOBALS['HTTP_RAW_POST_DATA'], 0, 1) === '<' ? 'XMLRPC' : 'JSON'; self::$_instance->request_method = substr($GLOBALS['HTTP_RAW_POST_DATA'], 0, 1) === '<' ? 'XMLRPC' : 'JSON';
return; return;
@ -1258,7 +1262,7 @@ class Context
} }
// Set JSON and XMLRPC arguments. // Set JSON and XMLRPC arguments.
if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST && !empty($GLOBALS['HTTP_RAW_POST_DATA'])) if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && empty($_POST) && !empty($GLOBALS['HTTP_RAW_POST_DATA']))
{ {
$params = array(); $params = array();
$request_method = self::getRequestMethod(); $request_method = self::getRequestMethod();

View file

@ -151,13 +151,20 @@ class HTMLDisplayHandler
Context::loadFile(array($edited_layout_css, 'all', '', 100)); Context::loadFile(array($edited_layout_css, 'all', '', 100));
} }
} }
if(!$layout_path) if (!$layout_path)
{ {
$layout_path = './common/tpl'; $layout_path = './common/tpl';
} }
if(!$layout_file) if (!$layout_file)
{ {
$layout_file = 'default_layout'; if ($layout_path === './common/tpl')
{
$layout_file = 'default_layout';
}
else
{
$layout_file = 'layout';
}
} }
$oTemplate = new Rhymix\Framework\Template; $oTemplate = new Rhymix\Framework\Template;

View file

@ -151,7 +151,16 @@ class ModuleHandler extends Handler
$site_module_info->domain = Rhymix\Framework\URL::getCurrentDomain(); $site_module_info->domain = Rhymix\Framework\URL::getCurrentDomain();
$site_module_info->is_default_domain = 'N'; $site_module_info->is_default_domain = 'N';
$site_module_info->is_default_replaced = true; $site_module_info->is_default_replaced = true;
// Reset context variables if the domain was replaced.
Context::set('site_module_info', $site_module_info); Context::set('site_module_info', $site_module_info);
Context::set('_default_url', null);
Context::set('request_uri', $current_url = Context::getRequestUri());
if ($query_string = http_build_query(Context::getCurrentRequest()->args))
{
$current_url .= '?' . $query_string;
}
Context::set('current_url', $current_url);
} }
} }
} }

View file

@ -44,24 +44,23 @@ class PageHandler extends Handler implements Iterator
$this->page_count = $page_count; $this->page_count = $page_count;
$this->point = 0; $this->point = 0;
$first_page = $cur_page - (int) ($page_count / 2); if ($this->cur_page > $total_page)
if($first_page < 1)
{ {
$first_page = 1; $this->cur_page = $total_page;
}
if ($this->page_count > $total_page)
{
$this->page_count = $total_page;
} }
if($total_page > $page_count && $first_page + $page_count - 1 > $total_page) $first_page = max(1, $this->cur_page - floor($this->page_count / 2));
if (($first_page + $this->page_count - 1) > $total_page)
{ {
$first_page -= $first_page + $page_count - 1 - $total_page; $first_page = max(1, $total_page - $this->page_count + 1);
} }
$this->first_page = $first_page; $this->first_page = $first_page;
$this->last_page = $total_page; $this->last_page = $total_page;
if($total_page < $this->page_count)
{
$this->page_count = $total_page;
}
} }
/** /**

View file

@ -1126,17 +1126,17 @@ class DB
} }
else else
{ {
$exceptions = []; $exceptions = ['TABLE'];
} }
// Add prefixes to all other table names in the query string. // 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]); $type = strtoupper($m[1]);
$tables = array_map(function($str) use($type, $exceptions) { $tables = array_map(function($str) use($type, $exceptions) {
return preg_replace_callback('/`?(\w+)`?(?:\s+AS\s+`?(\w+)`?)?/i', function($m) 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)) 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') elseif ($type === 'FROM' || $type === 'JOIN')
{ {

View file

@ -70,8 +70,21 @@ class DBTableParser extends BaseParser
// Load columns. // Load columns.
foreach ($xml->column as $column_info) 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. // Get the column name and type.
$column = new DBTable\Column;
$column->name = strval($column_info['name']); $column->name = strval($column_info['name']);
list($column->type, $column->xetype, $column->size) = self::getTypeAndSize(strval($column_info['type']), strval($column_info['size'])); 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. // Don't apply a filter if there is no variable.
$column = $this instanceof ColumnWrite ? $this->name : $this->column; $column = $this instanceof ColumnWrite ? $this->name : $this->column;
$filter = isset($this->filter) ? $this->filter : ''; $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 = ''; $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'; $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) if ($column->not_null)
{ {
$columndef .= ' 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) if ($column->auto_increment)
{ {
$columndef .= ' AUTO_INCREMENT'; $columndef .= ' AUTO_INCREMENT';
} }
$columns[] = $columndef; $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])); $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]); $codepoint = ((0x07 & $bytes[0]) << 18) + ((0x3F & $bytes[1]) << 12) + ((0x3F & $bytes[2]) << 6) + (0x3F & $bytes[3]);
return '&#x' . dechex($codepoint) . ';'; return '&#x' . dechex($codepoint) . ';';
}, (string)$str); }, (string)$str) ?? '';
} }
/** /**
@ -686,11 +686,11 @@ function utf8_normalize_spaces($str, bool $multiline = false): string
{ {
if ($multiline) 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 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) { chunkfail: function(e, res) {
lastUploadTime = Date.now(); lastUploadTime = Date.now();
if (chunkStatus) { 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; return chunkStatus = false;
} }
}, },
@ -169,7 +169,7 @@
result = jQuery.parseJSON(result); result = jQuery.parseJSON(result);
} }
if (!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; return false;
} }
@ -215,7 +215,7 @@
return false; return false;
} else { } else {
$container.data('editorStatus', null); $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; return false;
} }
}, },
@ -229,7 +229,7 @@
} }
}, 1000); }, 1000);
if (chunkStatus) { 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; return false;
} }
}, },

View file

@ -4,14 +4,18 @@
* This script runs the task queue. * This script runs the task queue.
* *
* Unlike other scripts provided with Rhymix, it can be called * 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); define('RXQUEUE_CRON', true);
// If called on the CLI, run additional checks. // If called on the CLI, run additional checks.
if (PHP_SAPI === 'cli') 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 else
{ {

View file

@ -56,11 +56,7 @@ class AdminAdminModel extends Admin
*/ */
public function getSiteAllList() public function getSiteAllList()
{ {
if(Context::get('domain')) $siteList = $this->getAllSitesThatHaveModules(Context::get('domain'));
{
$domain = Context::get('domain');
}
$siteList = $this->getAllSitesThatHaveModules($domain);
$this->add('site_list', $siteList); $this->add('site_list', $siteList);
} }

View file

@ -466,10 +466,12 @@ class CommentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen) if($strlen)
{ {
$content = cut_str($content, $strlen, '...'); $content = escape(cut_str($content, $strlen, '...'), false);
}
else
{
$content = escape($content);
} }
$content = escape($content);
if ($content === '') if ($content === '')
{ {
@ -511,9 +513,12 @@ class CommentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen) if($strlen)
{ {
$content = cut_str($content, $strlen, '...'); return escape(cut_str($content, $strlen, '...'), false);
}
else
{
return escape($content);
} }
return escape($content);
} }
/** /**

View file

@ -634,10 +634,12 @@ class DocumentItem extends BaseObject
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
if($strlen) if($strlen)
{ {
$content = cut_str($content, $strlen, '...'); return escape(cut_str($content, $strlen, '...'), false);
}
else
{
return escape($content);
} }
return escape($content);
} }
function getContentText($strlen = 0) function getContentText($strlen = 0)
@ -653,17 +655,22 @@ class DocumentItem extends BaseObject
} }
$content = preg_replace('!(</p>|</div>|<br)!i', ' $1', $this->get('content')); $content = preg_replace('!(</p>|</div>|<br)!i', ' $1', $this->get('content'));
$content = preg_replace_callback('/<(object|param|embed)[^>]*/is', array($this, '_checkAllowScriptAccess'), $content); //$content = preg_replace_callback('/<(object|param|embed)[^>]*/is', array($this, '_checkAllowScriptAccess'), $content);
$content = preg_replace_callback('/<object[^>]*>/is', array($this, '_addAllowScriptAccess'), $content); //$content = preg_replace_callback('/<object[^>]*>/is', array($this, '_addAllowScriptAccess'), $content);
if($strlen) if($strlen)
{ {
$content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content)))); $content = trim(utf8_normalize_spaces(html_entity_decode(strip_tags($content))));
$content = cut_str($content, $strlen, '...'); return escape(cut_str($content, $strlen, '...'), false);
}
else
{
return escape($content);
} }
return escape($content);
} }
/**
* @deprecated
*/
function _addAllowScriptAccess($m) function _addAllowScriptAccess($m)
{ {
if($this->allowscriptaccessList[$this->allowscriptaccessKey] == 1) if($this->allowscriptaccessList[$this->allowscriptaccessKey] == 1)
@ -674,6 +681,9 @@ class DocumentItem extends BaseObject
return $m[0]; return $m[0];
} }
/**
* @deprecated
*/
function _checkAllowScriptAccess($m) function _checkAllowScriptAccess($m)
{ {
if($m[1] == 'object') if($m[1] == 'object')
@ -806,8 +816,7 @@ class DocumentItem extends BaseObject
// Truncate string // Truncate string
$content = cut_str($content, $str_size, $tail); $content = cut_str($content, $str_size, $tail);
return escape($content, false);
return escape($content);
} }
function getRegdate($format = 'Y.m.d H:i:s', $conversion = true) function getRegdate($format = 'Y.m.d H:i:s', $conversion = true)

View file

@ -19,31 +19,32 @@ function memberSetEvent() {
// 실제 서버에 특정 필드의 value check를 요청하고 이상이 있으면 메세지를 뿌려주는 함수 // 실제 서버에 특정 필드의 value check를 요청하고 이상이 있으면 메세지를 뿌려주는 함수
function memberCheckValue(event) { function memberCheckValue(event) {
var field = event.target; var field = event.target;
var _name = field.name; if(!field.name || !field.value) {
var _value = field.value; return;
if(!_name || !_value) return; }
var params = {name:_name, value:_value}; exec_json('member.procMemberCheckValue', {
var response_tags = ['error','message']; name: field.name,
value: field.value
exec_xml('member','procMemberCheckValue', params, completeMemberCheckValue, response_tags, field); }, function(data) {
completeMemberCheckValue(data, null, field);
});
} }
// 서버에서 응답이 올 경우 이상이 있으면 메세지를 출력 // 서버에서 응답이 올 경우 이상이 있으면 메세지를 출력
function completeMemberCheckValue(ret_obj, response_tags, field) { function completeMemberCheckValue(data, unused, field) {
var _id = 'dummy_check'+field.name; var _id = 'dummy_check'+field.name;
var dummy = jQuery('#'+_id); var dummy = jQuery('#'+_id);
if(ret_obj['message']=='success') {
dummy.html('').hide();
return;
}
if (!dummy.length) { if (!dummy.length) {
dummy = jQuery('<p class="checkValue help-inline" style="color:red" />').attr('id', _id).appendTo(field.parentNode); dummy = jQuery('<p class="checkValue help-inline" style="color:red" />').attr('id', _id).appendTo(field.parentNode);
} }
dummy.html(ret_obj['message']).show(); if(data.message == 'success') {
dummy.html('').hide();
return;
} else {
dummy.html(data.message).show();
}
} }
// 결과 메세지를 정리하는 함수 // 결과 메세지를 정리하는 함수

View file

@ -443,6 +443,10 @@ class ModuleController extends Module
{ {
$oMenuAdminController = getAdminController('menu'); $oMenuAdminController = getAdminController('menu');
$menuSrl = $oMenuAdminController->getUnlinkedMenu(); $menuSrl = $oMenuAdminController->getUnlinkedMenu();
if ($menuSrl instanceof BaseObject && !$menuSrl->toBool())
{
return $menuSrl;
}
$menuArgs->menu_srl = $menuSrl; $menuArgs->menu_srl = $menuSrl;
$menuArgs->menu_item_srl = getNextSequence(); $menuArgs->menu_item_srl = getNextSequence();

View file

@ -1,7 +1,11 @@
<query id="getDomainInfo" action="select"> <query id="getDomainInfo" action="select">
<tables> <tables>
<table name="domains" /> <table name="domains" />
<table name="modules" /> <table name="modules" type="left join">
<conditions>
<condition operation="equal" column="modules.module_srl" default="domains.index_module_srl" />
</conditions>
</table>
</tables> </tables>
<columns> <columns>
<column name="domains.*" /> <column name="domains.*" />
@ -9,7 +13,6 @@
<column name="domains.domain_srl" alias="domain_srl" /> <column name="domains.domain_srl" alias="domain_srl" />
</columns> </columns>
<conditions> <conditions>
<condition operation="equal" column="modules.module_srl" default="domains.index_module_srl" notnull="notnull" />
<condition operation="equal" column="domains.domain_srl" var="domain_srl" pipe="and" /> <condition operation="equal" column="domains.domain_srl" var="domain_srl" pipe="and" />
<condition operation="equal" column="domains.domain" var="domain" pipe="and" /> <condition operation="equal" column="domains.domain" var="domain" pipe="and" />
<condition operation="equal" column="domains.is_default_domain" var="is_default_domain" pipe="and" /> <condition operation="equal" column="domains.is_default_domain" var="is_default_domain" pipe="and" />

View file

@ -28,7 +28,7 @@
<item loop="$document_list=>$oDocument" rdf:about="{$oDocument->getPermanentUrl()}"> <item loop="$document_list=>$oDocument" rdf:about="{$oDocument->getPermanentUrl()}">
<title>{$oDocument->getTitleText()}</title> <title>{$oDocument->getTitleText()}</title>
<link>{$oDocument->getPermanentUrl()}</link> <link>{$oDocument->getPermanentUrl()}</link>
<description>{$oDocument->getSummary(400)|escape}</description> <description>{$oDocument->getSummary(400)}</description>
<dc:creator>{$oDocument->getNickName()}</dc:creator> <dc:creator>{$oDocument->getNickName()}</dc:creator>
<dc:date>{date('c', ztime($oDocument->get('regdate')))}</dc:date> <dc:date>{date('c', ztime($oDocument->get('regdate')))}</dc:date>
</item> </item>

View file

@ -22,7 +22,7 @@
<!--@if($target_modules[$oDocument->get('module_srl')] == 'Y')--> <!--@if($target_modules[$oDocument->get('module_srl')] == 'Y')-->
<description>{\Rhymix\Framework\Filters\HTMLFilter::fixRelativeUrls(utf8_trim(utf8_normalize_spaces($oDocument->get('content'))))|escape}</description> <description>{\Rhymix\Framework\Filters\HTMLFilter::fixRelativeUrls(utf8_trim(utf8_normalize_spaces($oDocument->get('content'))))|escape}</description>
<!--@else--> <!--@else-->
<description>{$oDocument->getSummary(400)|escape}</description> <description>{$oDocument->getSummary(400)}</description>
<!--@end--> <!--@end-->
<category cond="$oDocument->getModuleName()">{Context::replaceUserLang($oDocument->getModuleName())}</category> <category cond="$oDocument->getModuleName()">{Context::replaceUserLang($oDocument->getModuleName())}</category>
<category cond="$oDocument->get('category_srl') && $category_name = $category_list[$oDocument->get('module_srl')][$oDocument->get('category_srl')]->title">{Context::replaceUserLang($category_name)}</category> <category cond="$oDocument->get('category_srl') && $category_name = $category_list[$oDocument->get('module_srl')][$oDocument->get('category_srl')]->title">{Context::replaceUserLang($category_name)}</category>

View file

@ -0,0 +1,9 @@
<table name="generated">
<column name="id" type="bignumber" size="11" notnull="notnull" auto_increment="auto_increment" primary_key="primary_key" />
<column name="module_srl" type="number" notnull="notnull" index="idx_module_srl" />
<column name="document_srl" type="number" notnull="notnull" index="idx_document_srl" />
<column name="member_srl" type="number" notnull="notnull" index="idx_member_srl" />
<column name="gentest1" type="number" generated="always" default="document_srl + member_srl" stored="true" notnull="notnull" />
<column name="gentest2" type="number" generated="always" default="MAX(module_srl, document_srl)" stored="false" />
<column name="gentest3" type="varchar" size="40" notnull="notnull" generated="always" default="CONCAT(module_srl, '_', document_srl)" />
</table>

View file

@ -175,6 +175,22 @@ class DBTest extends \Codeception\Test\Unit
$target = 'INSERT INTO `' . $prefix . 'documents` (a, b, c) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE b = ?, c = ?'; $target = 'INSERT INTO `' . $prefix . 'documents` (a, b, c) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE b = ?, c = ?';
$this->assertEquals($target, $oDB->addPrefixes($source)); $this->assertEquals($target, $oDB->addPrefixes($source));
$source = "LOAD DATA LOCAL INFILE '/tmp/foo.csv' INTO TABLE foo_table FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (a, b, c)";
$target = "LOAD DATA LOCAL INFILE '/tmp/foo.csv' INTO TABLE `" . $prefix . "foo_table` FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (a, b, c)";
$this->assertEquals($target, $oDB->addPrefixes($source));
$source = 'ALTER TABLE documents ADD INDEX idx_foo (a, b)';
$target = 'ALTER TABLE `' . $prefix . 'documents` ADD INDEX idx_foo (a, b)';
$this->assertEquals($target, $oDB->addPrefixes($source));
$source = 'TRUNCATE TABLE documents';
$target = 'TRUNCATE TABLE `' . $prefix . 'documents`';
$this->assertEquals($target, $oDB->addPrefixes($source));
$source = 'DROP TABLE documents';
$target = 'DROP TABLE `' . $prefix . 'documents`';
$this->assertEquals($target, $oDB->addPrefixes($source));
$source = 'update documents set a = ?, b = ? where c = ?'; $source = 'update documents set a = ?, b = ? where c = ?';
$this->assertEquals($source, $oDB->addPrefixes($source)); $this->assertEquals($source, $oDB->addPrefixes($source));

View file

@ -63,4 +63,14 @@ class DBTableParserTest extends \Codeception\Test\Unit
$this->assertStringContainsString('CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci', $sql); $this->assertStringContainsString('CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci', $sql);
$this->assertStringContainsString('ENGINE = InnoDB', $sql); $this->assertStringContainsString('ENGINE = InnoDB', $sql);
} }
public function testGeneratedColumn()
{
$table = Rhymix\Framework\Parsers\DBTableParser::loadXML(\RX_BASEDIR . 'tests/_data/dbtable/generated.xml');
$sql = $table->getCreateQuery('rx_');
$this->assertStringContainsString('CREATE TABLE `rx_generated`', $sql);
$this->assertStringContainsString('`gentest1` BIGINT GENERATED ALWAYS AS (document_srl + member_srl) STORED NOT NULL,', $sql);
$this->assertStringContainsString('`gentest2` BIGINT GENERATED ALWAYS AS (MAX(module_srl, document_srl)),', $sql);
$this->assertStringContainsString('`gentest3` VARCHAR(40) GENERATED ALWAYS AS (CONCAT(module_srl, \'_\', document_srl)) NOT NULL,', $sql);
}
} }