Merge pull request #2412 from kijin/pr/extra-vars

확장변수 기능 강화 (파일 업로드 지원 등)
This commit is contained in:
Kijin Sung 2024-10-09 17:00:05 +09:00 committed by GitHub
commit 206521a352
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 600 additions and 80 deletions

View file

@ -174,8 +174,14 @@ class DocumentAdminController extends Document
$var_idx = Context::get('var_idx');
$name = Context::get('name');
$type = Context::get('type');
$is_required = Context::get('is_required');
$default = Context::get('default');
$is_required = Context::get('is_required') === 'Y' ? 'Y' : 'N';
$is_strict = Context::get('is_strict') === 'Y' ? 'Y' : 'N';
$default = trim(utf8_clean(Context::get('default')));
$options = trim(utf8_clean(Context::get('options')));
if ($options !== '')
{
$options = array_map('trim', explode("\n", $options));
}
$desc = Context::get('desc') ? Context::get('desc') : '';
$search = Context::get('search');
$eid = Context::get('eid');
@ -201,8 +207,11 @@ class DocumentAdminController extends Document
}
// insert or update
$oDocumentController = getController('document');
$output = $oDocumentController->insertDocumentExtraKey($module_srl, $var_idx, $name, $type, $is_required, $search, $default, $desc, $eid);
$oDocumentController = DocumentController::getInstance();
$output = $oDocumentController->insertDocumentExtraKey(
$module_srl, $var_idx, $name, $type, $is_required, $search,
$default, $desc, $eid, $is_strict, $options
);
if(!$output->toBool()) return $output;
$this->setMessage('success_registed');

View file

@ -109,6 +109,10 @@ class Document extends ModuleObject
if(!$oDB->isColumnExists('document_categories', 'is_default')) return true;
if(!$oDB->isIndexExists('document_categories', 'idx_list_order')) return true;
// 2024.10.08 Add columns to document_extra_keys table
if(!$oDB->isColumnExists('document_extra_keys', 'var_is_strict')) return true;
if(!$oDB->isColumnExists('document_extra_keys', 'var_options')) return true;
return false;
}
@ -219,6 +223,16 @@ class Document extends ModuleObject
{
$oDB->addIndex('document_categories', 'idx_list_order', array('list_order'));
}
// 2024.10.08 Add columns to document_extra_keys table
if(!$oDB->isColumnExists('document_extra_keys', 'var_is_strict'))
{
$oDB->addColumn('document_extra_keys', 'var_is_strict', 'char', '1', 'N', true, 'var_is_required');
}
if(!$oDB->isColumnExists('document_extra_keys', 'var_options'))
{
$oDB->addColumn('document_extra_keys', 'var_options', 'text', '', '', false, 'var_default');
}
}
/**

View file

@ -818,7 +818,11 @@ class DocumentController extends Document
if(isset($obj->{'extra_vars'.$idx}))
{
$tmp = $obj->{'extra_vars'.$idx};
if(is_array($tmp))
if ($extra_item->type === 'file')
{
$value = $tmp;
}
elseif (is_array($tmp))
{
$value = implode('|@|', $tmp);
}
@ -831,7 +835,37 @@ class DocumentController extends Document
{
$value = trim($obj->{$extra_item->name});
}
if($value == NULL) continue;
// Validate and process the extra value.
if ($value == NULL && $manual_inserted)
{
continue;
}
else
{
if (!$manual_inserted)
{
$ev_output = $extra_item->validate($value);
if ($ev_output && !$output->toBool())
{
$oDB->rollback();
return $ev_output;
}
}
// Handle extra vars that support file upload.
if ($extra_item->type === 'file' && is_array($value))
{
$ev_output = $extra_item->uploadFile($value, $obj->document_srl, 'doc');
if (!$ev_output->toBool())
{
$oDB->rollback();
return $ev_output;
}
$value = $ev_output->get('file_srl');
}
}
$extra_vars[$extra_item->name] = $value;
$this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, $idx, $value, $extra_item->eid);
}
@ -1153,7 +1187,10 @@ class DocumentController extends Document
$extra_vars = array();
if(Context::get('act')!='procFileDelete')
{
// Get a copy of current extra vars before deleting all existing data.
$old_extra_vars = DocumentModel::getExtraVars($obj->module_srl, $obj->document_srl);
$this->deleteDocumentExtraVars($source_obj->get('module_srl'), $obj->document_srl, null, Context::getLangType());
// Insert extra variables if the document successfully inserted.
$extra_keys = DocumentModel::getExtraKeys($obj->module_srl);
if(count($extra_keys))
@ -1164,13 +1201,98 @@ class DocumentController extends Document
if(isset($obj->{'extra_vars'.$idx}))
{
$tmp = $obj->{'extra_vars'.$idx};
if(is_array($tmp))
if ($extra_item->type === 'file')
{
$value = $tmp;
}
elseif (is_array($tmp))
{
$value = implode('|@|', $tmp);
}
else
{
$value = trim($tmp);
}
}
elseif (isset($obj->{$extra_item->name}))
{
$value = trim($obj->{$extra_item->name});
}
// Validate and process the extra value.
if ($value == NULL && $manual_updated && $extra_item->type !== 'file')
{
continue;
}
else
{
// Check for required and strict values.
if (!$manual_updated)
{
$ev_output = $extra_item->validate($value, $old_extra_vars[$idx]->value ?? null);
if ($ev_output && !$ev_output->toBool())
{
$oDB->rollback();
return $ev_output;
}
}
// Handle extra vars that support file upload.
if ($extra_item->type === 'file')
{
// New upload
if (is_array($value) && isset($value['name']))
{
// Delete old file
if (isset($old_extra_vars[$idx]->value))
{
$fc_output = FileController::getInstance()->deleteFile($old_extra_vars[$idx]->value);
if (!$fc_output->toBool())
{
$oDB->rollback();
return $fc_output;
}
}
// Insert new file
$ev_output = $extra_item->uploadFile($value, $obj->document_srl, 'doc');
if (!$ev_output->toBool())
{
$oDB->rollback();
return $ev_output;
}
$value = $ev_output->get('file_srl');
}
// Delete current file
elseif (isset($obj->{'_delete_extra_vars'.$idx}) && $obj->{'_delete_extra_vars'.$idx} === 'Y')
{
if (isset($old_extra_vars[$idx]->value))
{
// Check if deletion is allowed
$ev_output = $extra_item->validate(null);
if (!$ev_output->toBool())
{
$oDB->rollback();
return $ev_output;
}
// Delete old file
$fc_output = FileController::getInstance()->deleteFile($old_extra_vars[$idx]->value);
if (!$fc_output->toBool())
{
$oDB->rollback();
return $fc_output;
}
}
}
// Leave current file unchanged
elseif (!$value)
{
if (isset($old_extra_vars[$idx]->value))
{
$value = $old_extra_vars[$idx]->value;
}
}
}
}
else if(isset($obj->{$extra_item->name})) $value = trim($obj->{$extra_item->name});
if($value == NULL) continue;
$extra_vars[$extra_item->name] = $value;
$this->insertDocumentExtraVar($obj->module_srl, $obj->document_srl, $idx, $value, $extra_item->eid);
}
@ -1611,11 +1733,16 @@ class DocumentController extends Document
* @param string $var_default
* @param string $var_desc
* @param int $eid
* @param string $var_is_strict
* @param array $var_options
* @return object
*/
function insertDocumentExtraKey($module_srl, $var_idx, $var_name, $var_type, $var_is_required = 'N', $var_search = 'N', $var_default = '', $var_desc = '', $eid = 0)
function insertDocumentExtraKey($module_srl, $var_idx, $var_name, $var_type, $var_is_required = 'N', $var_search = 'N', $var_default = '', $var_desc = '', $eid = 0, $var_is_strict = 'N', $var_options = null)
{
if(!$module_srl || !$var_idx || !$var_name || !$var_type || !$eid) return new BaseObject(-1, 'msg_invalid_request');
if (!$module_srl || !$var_idx || !$var_name || !$var_type || !$eid)
{
return new BaseObject(-1, 'msg_invalid_request');
}
$obj = new stdClass();
$obj->module_srl = $module_srl;
@ -1623,8 +1750,10 @@ class DocumentController extends Document
$obj->var_name = $var_name;
$obj->var_type = $var_type;
$obj->var_is_required = $var_is_required=='Y'?'Y':'N';
$obj->var_is_strict = $var_is_strict=='Y'?'Y':'N';
$obj->var_search = $var_search=='Y'?'Y':'N';
$obj->var_default = $var_default;
$obj->var_options = $var_options ? json_encode($var_options, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES) : null;
$obj->var_desc = $var_desc;
$obj->eid = $eid;
@ -2553,8 +2682,6 @@ class DocumentController extends Document
$js_code[] = 'var validator = xe.getApp("validator")[0];';
$js_code[] = 'if(!validator) return false;';
$logged_info = Context::get('logged_info');
foreach($extra_keys as $idx => $val)
{
$idx = $val->idx;
@ -2562,9 +2689,11 @@ class DocumentController extends Document
{
$idx .= '[]';
}
$name = str_ireplace(array('<script', '</script'), array('<scr" + "ipt', '</scr" + "ipt'), $val->name);
$js_code[] = sprintf('validator.cast("ADD_MESSAGE", ["extra_vars%s","%s"]);', $idx, $name);
if($val->is_required == 'Y') $js_code[] = sprintf('validator.cast("ADD_EXTRA_FIELD", ["extra_vars%s", { required:true }]);', $idx);
$js_code[] = sprintf('validator.cast("ADD_MESSAGE", ["extra_vars%s", %s]);', $idx, var_export($val->name, true));
if($val->is_required == 'Y' && $val->type !== 'file')
{
$js_code[] = sprintf('validator.cast("ADD_EXTRA_FIELD", ["extra_vars%s", { required:true }]);', $idx);
}
}
$js_code[] = '})(jQuery);';
@ -3653,7 +3782,7 @@ Content;
{
foreach($documentExtraKeys AS $extraItem)
{
$this->insertDocumentExtraKey($value, $extraItem->idx, $extraItem->name, $extraItem->type, $extraItem->is_required , $extraItem->search , $extraItem->default , $extraItem->desc, $extraItem->eid) ;
$this->insertDocumentExtraKey($value, $extraItem->idx, $extraItem->name, $extraItem->type, $extraItem->is_required , $extraItem->search , $extraItem->default , $extraItem->desc, $extraItem->eid, $extraItem->is_strict, $extraItem->options);
}
}
}

View file

@ -8,10 +8,12 @@
<column name="var_name" alias="name" />
<column name="var_type" alias="type" />
<column name="var_is_required" alias="is_required" />
<column name="var_is_strict" alias="is_strict" />
<column name="var_search" alias="search" />
<column name="var_default" alias="default" />
<column name="var_options" alias="options" />
<column name="var_desc" alias="desc" />
<column name="eid" alias="eid" />
<column name="eid" alias="eid" />
</columns>
<conditions>
<condition operation="equal" column="module_srl" var="module_srl" filter="number" notnull="notnull" />

View file

@ -1,16 +1,18 @@
<query id="insertDocumentExtraKey" action="insert">
<tables>
<table name="document_extra_keys" />
</tables>
<columns>
<column name="module_srl" var="module_srl" filter="number" notnull="notnull" />
<column name="var_idx" var="var_idx" filter="number" notnull="notnull" />
<column name="var_name" var="var_name" notnull="notnull" />
<column name="var_type" var="var_type" notnull="notnull" />
<column name="var_is_required" var="var_is_required" default="N" notnull="notnull" />
<column name="var_search" var="var_search" default="N" notnull="notnull" />
<column name="var_default" var="var_default" />
<column name="var_desc" var="var_desc" />
<column name="eid" var="eid" notnull="notnull" />
</columns>
<tables>
<table name="document_extra_keys" />
</tables>
<columns>
<column name="module_srl" var="module_srl" filter="number" notnull="notnull" />
<column name="var_idx" var="var_idx" filter="number" notnull="notnull" />
<column name="var_name" var="var_name" notnull="notnull" />
<column name="var_type" var="var_type" notnull="notnull" />
<column name="var_is_required" var="var_is_required" default="N" notnull="notnull" />
<column name="var_is_strict" var="var_is_strict" default="N" notnull="notnull" />
<column name="var_search" var="var_search" default="N" notnull="notnull" />
<column name="var_default" var="var_default" />
<column name="var_options" var="var_options" />
<column name="var_desc" var="var_desc" />
<column name="eid" var="eid" notnull="notnull" />
</columns>
</query>

View file

@ -1,18 +1,20 @@
<query id="updateDocumentExtraKey" action="update">
<tables>
<table name="document_extra_keys" />
</tables>
<columns>
<column name="var_name" var="var_name" notnull="notnull" />
<column name="var_type" var="var_type" notnull="notnull" />
<column name="var_is_required" var="var_is_required" default="N" notnull="notnull" />
<column name="var_search" var="var_search" default="N" notnull="notnull" />
<column name="var_default" var="var_default" default="" />
<column name="var_desc" var="var_desc" />
<column name="eid" var="eid" notnull="notnull" />
</columns>
<conditions>
<condition operation="equal" column="module_srl" var="module_srl" filter="number" notnull="notnull" />
<condition operation="equal" column="var_idx" var="var_idx" filter="number" notnull="notnull" pipe="and" />
</conditions>
<tables>
<table name="document_extra_keys" />
</tables>
<columns>
<column name="var_name" var="var_name" notnull="notnull" />
<column name="var_type" var="var_type" notnull="notnull" />
<column name="var_is_required" var="var_is_required" default="N" notnull="notnull" />
<column name="var_is_strict" var="var_is_strict" default="N" notnull="notnull" />
<column name="var_search" var="var_search" default="N" notnull="notnull" />
<column name="var_default" var="var_default" default="" />
<column name="var_options" var="var_options" default="" />
<column name="var_desc" var="var_desc" />
<column name="eid" var="eid" notnull="notnull" />
</columns>
<conditions>
<condition operation="equal" column="module_srl" var="module_srl" filter="number" notnull="notnull" />
<condition operation="equal" column="var_idx" var="var_idx" filter="number" notnull="notnull" pipe="and" />
</conditions>
</query>

View file

@ -4,8 +4,10 @@
<column name="var_name" type="varchar" size="250" notnull="notnull" />
<column name="var_type" type="varchar" size="50" notnull="notnull" />
<column name="var_is_required" type="char" size="1" default="N" notnull="notnull" />
<column name="var_is_strict" type="char" size="1" default="N" notnull="notnull" />
<column name="var_search" type="char" size="1" default="N" notnull="notnull" />
<column name="var_default" type="text" />
<column name="var_options" type="text" />
<column name="var_desc" type="text" />
<column name="eid" type="varchar" size="40" />
</table>

View file

@ -49,6 +49,14 @@
<label class="x_inline" for="is_required_n"><input type="radio" name="is_required" id="is_required_n" value="N" checked="checked"|cond="$selected_var->is_required != 'Y'" /> {$lang->not}</label>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->extra_vars_is_strict}</label>
<div class="x_controls">
<label class="x_inline" for="is_strict_y"><input type="radio" name="is_strict" id="is_strict_y" value="Y" checked="checked"|cond="$selected_var->is_strict == 'Y'" /> {$lang->yes}</label>
<label class="x_inline" for="is_strict_n"><input type="radio" name="is_strict" id="is_strict_n" value="N" checked="checked"|cond="$selected_var->is_strict != 'Y'" /> {$lang->not}</label>
<p class="x_help-block">{$lang->about_extra_vars_is_strict}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="default">{$lang->default_value}</label>
<div class="x_controls">
@ -56,6 +64,13 @@
<p class="x_help-block">{$lang->about_extra_vars_default_value}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="default">{$lang->extra_vars_options}</label>
<div class="x_controls">
<textarea type="text" name="options" id="options">{$selected_var ? implode("\n", $selected_var->getOptions()) : ''}</textarea>
<p class="x_help-block">{$lang->about_extra_vars_options}</p>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="lang_desc">{$lang->description}</label>
<div class="x_controls">

View file

@ -2,6 +2,11 @@
namespace Rhymix\Modules\Extravar\Models;
use BaseObject;
use Context;
use FileController;
use FileHandler;
use FileModel;
use ModuleModel;
use Rhymix\Framework\DateTime;
use Rhymix\Framework\i18n;
@ -25,7 +30,9 @@ class Value
public $name = '';
public $desc = '';
public $default = null;
public $options = null;
public $is_required = 'N';
public $is_strict = 'N';
public $is_disabled = 'N';
public $is_readonly = 'N';
public $search = 'N';
@ -55,6 +62,15 @@ class Value
'kr_zip' => true,
];
/**
* List of types that can have options.
*/
public const OPTION_TYPES = [
'checkbox' => true,
'radio' => true,
'select' => true,
];
/**
* Constructor for compatibility with legacy ExtraItem class.
*
@ -68,8 +84,11 @@ class Value
* @param string $search (Y, N)
* @param string $value
* @param string $eid
* @param string $parent_type
* @param string $is_strict
* @param string $options
*/
function __construct(int $module_srl, int $idx, string $name, string $type = 'text', $default = null, $desc = '', $is_required = 'N', $search = 'N', $value = null, string $eid = '')
function __construct(int $module_srl, int $idx, string $name, string $type = 'text', $default = null, $desc = '', $is_required = 'N', $search = 'N', $value = null, $eid = '', $parent_type = 'document', $is_strict = '', $options = null)
{
if (!$idx)
{
@ -80,11 +99,14 @@ class Value
$this->idx = $idx;
$this->eid = $eid;
$this->type = $type;
$this->parent_type = $parent_type;
$this->value = $value;
$this->name = $name;
$this->desc = $desc;
$this->default = $default;
$this->options = $options ? json_decode($options) : null;
$this->is_required = $is_required;
$this->is_strict = $is_strict;
$this->search = $search;
}
@ -139,6 +161,162 @@ class Value
return $template->compile();
}
/**
* Get the default value.
*
* @return mixed
*/
public function getDefaultValue()
{
if (!$this->canHaveOptions())
{
return $this->default;
}
elseif (is_array($this->options))
{
return $this->default;
}
else
{
return null;
}
}
/**
* Get options specified by the administrator.
*
* @return array
*/
public function getOptions(): array
{
if (!$this->canHaveOptions())
{
return $this->options ?? [];
}
if (is_array($this->options))
{
return $this->options;
}
elseif ($this->default)
{
return is_array($this->default) ? $this->default : explode(',', $this->default);
}
else
{
return [];
}
}
/**
* Check if the current value can have options.
*
* @return bool
*/
public function canHaveOptions(): bool
{
return isset(self::OPTION_TYPES[$this->type]);
}
/**
* Check if the current value is an array type.
*
* @return bool
*/
public function isArrayType(): bool
{
return isset(self::ARRAY_TYPES[$this->type]);
}
/**
* Validate a value.
*
* @param mixed $value
* @param mixed $old_value
* @return ?BaseObject
*/
public function validate($value, $old_value = null): ?BaseObject
{
// Take legacy encoding into consideration.
if (is_array($value))
{
$is_array = true;
$values = $value;
}
elseif (str_contains($value, '|@|'))
{
$is_array = true;
$values = explode('|@|', $value);
}
else
{
$is_array = false;
$values = [$value];
}
// Check if a required value is empty.
if ($this->is_required === 'Y')
{
if ($this->type === 'file' && !$value && $old_value)
{
$value = $old_value;
$values = (array)$old_value;
}
if ($is_array && trim(implode('', $values)) === '')
{
return new BaseObject(-1, sprintf(lang('common.filter.isnull'), Context::replaceUserLang($this->name)));
}
if (!$is_array && trim(strval($value)) === '')
{
return new BaseObject(-1, sprintf(lang('common.filter.isnull'), Context::replaceUserLang($this->name)));
}
}
// Check if a strict value is not one of the specified options.
if ($this->is_strict === 'Y' && $value)
{
if ($this->canHaveOptions())
{
$options = $this->getOptions();
foreach ($values as $v)
{
if (!in_array($v, $options))
{
return new BaseObject(-1, sprintf(lang('common.filter.equalto'), Context::replaceUserLang($this->name)));
}
}
}
elseif ($this->isArrayType())
{
if (!$is_array)
{
return new BaseObject(-1, sprintf(lang('common.filter.equalto'), Context::replaceUserLang($this->name)));
}
}
}
return null;
}
/**
* Upload a file.
*
* @param array $file
* @param int $target_srl
* @param string $target_type
* @return BaseObject
*/
public function uploadFile(array $file, int $target_srl, string $target_type): BaseObject
{
$oFileController = FileController::getInstance();
$output = $oFileController->insertFile($file, $this->module_srl, $target_srl);
if ($output->toBool())
{
$oFileController->setFilesValid($target_srl, "ev:$target_type", $output->get('file_srl'));
}
return $output;
}
/**
* Get the next temporary ID.
*
@ -185,14 +363,24 @@ class Value
{
$values = $value;
}
elseif (preg_match('/^[\[\{].*[\]\}]$/', $value))
{
$values = json_decode($value, true);
if (!is_array($values))
{
$values = [];
}
}
elseif (str_contains($value, '|@|'))
{
$values = explode('|@|', $value);
}
/*
elseif (str_contains($value, ',') && $type !== 'kr_zip')
{
$values = explode(',', $value);
}
*/
else
{
$values = [$value];
@ -213,6 +401,12 @@ class Value
return escape($value, false);
}
// Process the file upload type.
if ($type === 'file')
{
return $value ? intval($value) : null;
}
// Escape and return all other types.
return escape($value, false);
}
@ -287,6 +481,23 @@ class Value
return sprintf('%s-%s-%s', substr($value, 0, 4), substr($value, 4, 2), substr($value, 6, 2));
case 'timezone':
return DateTime::getTimezoneList()[$value] ?? '';
case 'file':
if ($value)
{
$file = FileModel::getFile($value);
if ($file)
{
return sprintf('<span><a href="%s">%s</a> (%s)</span>', \RX_BASEURL . ltrim($file->download_url, './'), $file->source_filename, FileHandler::filesize($file->file_size));
}
else
{
return '';
}
}
else
{
return '';
}
default:
return $value;
}

View file

@ -50,7 +50,7 @@ class ValueCollection
foreach ($keys as $val)
{
$this->keys[$val->idx] = new Value($val->module_srl, $val->idx, $val->name, $val->type, $val->default, $val->desc, $val->is_required, $val->search, $val->value ?? null, $val->eid, $val->parent_type ?? 'document');
$this->keys[$val->idx] = new Value($val->module_srl, $val->idx, $val->name, $val->type, $val->default, $val->desc, $val->is_required, $val->search, $val->value ?? null, $val->eid, $val->parent_type ?? 'document', $val->is_strict, $val->options);
}
}

View file

@ -0,0 +1,26 @@
'use strict';
(function($) {
$(function() {
$('button.evFileRemover').on('click', function() {
const container = $(this).parents('.ev_file_upload');
container.find('span.filename').text('');
container.find('span.filesize').text('');
container.find('input[type=hidden][name^=_delete_]').val('Y');
container.find('input[type=file]').val('');
});
$('input.rx_ev_file').on('change', function() {
const container = $(this).parents('.ev_file_upload');
const max_size = parseInt($(this).data('allowedFilesize'), 10);
const file_count = this.files.length;
for (let i = 0; i < file_count; i++) {
if (max_size && this.files[i].size > max_size) {
alert($(this).data('msgFilesize'));
$(this).val('');
return;
}
}
container.find('input[type=hidden][name^=_delete_]').val('N');
});
});
})(jQuery);

View file

@ -41,6 +41,9 @@
@case ('time')
@include ('form_types/datetime')
@break
@case ('file')
@include ('form_types/file_upload')
@break
@default
@include ('form_types/text')
@endswitch

View file

@ -1,10 +1,15 @@
@php
$has_value = is_array($value);
$default_value = $definition->getDefaultValue();
@endphp
@if ($parent_type === 'member')
<div class="rx_ev_{{ $type }}" style="padding-top:5px">
@foreach ($default ?? [] as $v)
@foreach ($definition->getOptions() as $v)
@php
$column_suffix = $type === 'checkbox' ? '[]' : '';
$tempid = $definition->getNextTempID();
$is_checked = is_array($value) && in_array(trim($v), $value);
$is_checked = $has_value ? in_array($v, $value) : ($v === $default_value);
@endphp
<label for="{{ $tempid }}">
<input type="{{ $type }}" name="{{ $input_name . $column_suffix }}"
@ -19,11 +24,11 @@
</div>
@else
<ul class="rx_ev_{{ $type }}">
@foreach ($default ?? [] as $v)
@foreach ($definition->getOptions() as $v)
@php
$column_suffix = $type === 'checkbox' ? '[]' : '';
$tempid = $definition->getNextTempID();
$is_checked = is_array($value) && in_array(trim($v), $value);
$is_checked = $has_value ? in_array($v, $value) : ($v === $default_value);
@endphp
<li>
<input type="{{ $type }}" name="{{ $input_name . $column_suffix }}"

View file

@ -0,0 +1,38 @@
@load('../assets/file_upload.js')
<div class="ev_file_upload">
@if ($value)
@php
$file = FileModel::getFile(intval($value));
@endphp
@if ($file)
<div class="ev_file_info">
<span class="filename">{{ $file->source_filename }}</span>
<span class="filesize">({{ FileHandler::filesize($file->file_size) }})</span>
<input type="hidden" name="_delete_{{ $input_name }}" value="N" />
<button type="button" class="btn evFileRemover">{{ lang('cmd_delete') }}</button>
</div>
@endif
@endif
@php
$file_config = FileModel::getUploadConfig($definition->module_srl);
$allowed_filetypes = strtr($file_config->allowed_filetypes ?? '', ['*.' => '.', ';' => ',']);
$allowed_filesize = ($file_config->allowed_filesize ?? 0) * 1024 * 1024;
@endphp
<div class="ev_file_input">
<input type="file" name="{{ $input_name }}"
id="{{ $input_id }}"|if="$input_id" class="file rx_ev_file"
style="{{ $definition->style }}"|if="$definition->style"
accept="{{ $allowed_filetypes }}"|if="$allowed_filetypes !== '' && $allowed_filetypes !== '.*'"
data-allowed-filesize="{{ $allowed_filesize }}"
data-msg-filesize="{{ lang('file.msg_exceeds_limit_size') }}"
@required(toBool($definition->is_required) && !$value)
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))
/>
</div>
</div>

View file

@ -1,10 +1,15 @@
@php
$has_value = is_array($value);
$default_value = $definition->getDefaultValue();
@endphp
<select name="{{ $input_name }}"
id="{{ $input_id }}"|if="$input_id" class="select rx_ev_select"
style="{{ $definition->style }}"|if="$definition->style"
@required(toBool($definition->is_required))
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))>
@foreach ($default ?: [] as $v)
<option value="{{ $v }}" @selected(is_array($value) && in_array(trim($v), $value))>{{ $v }}</option>
@foreach ($definition->getOptions() as $v)
<option value="{{ $v }}" @selected($has_value ? in_array($v, $value) : ($v === $default_value))>{{ $v }}</option>
@endforeach
</select>

View file

@ -2,7 +2,7 @@
<input type="url" name="{{ $input_name }}"
id="{{ $input_id }}"|if="$input_id" class="homepage rx_ev_url"
style="{{ $definition->style }}"|if="$definition->style"
value="{{ $value }}"
value="{{ strval($value) !== '' ? $value : $default }}"
@required(toBool($definition->is_required))
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))
@ -11,7 +11,16 @@
<input type="email" name="{{ $input_name }}"
id="{{ $input_id }}"|if="$input_id" class="email_address rx_ev_email"
style="{{ $definition->style }}"|if="$definition->style"
value="{{ $value }}"
value="{{ strval($value) !== '' ? $value : $default }}"
@required(toBool($definition->is_required))
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))
/>
@elseif ($type === 'number')
<input type="number" name="{{ $input_name }}"
id="{{ $input_id }}"|if="$input_id" class="number rx_ev_number"
style="{{ $definition->style }}"|if="$definition->style"
value="{{ strval($value) !== '' ? $value : $default }}"
@required(toBool($definition->is_required))
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))

View file

@ -4,4 +4,4 @@
@required(toBool($definition->is_required))
@disabled(toBool($definition->is_disabled))
@readonly(toBool($definition->is_readonly))
rows="8" cols="42">{{ $value }}</textarea>
rows="8" cols="42">{{ $value !== null ? $value : $definition->getDefaultValue() }}</textarea>

View file

@ -127,9 +127,9 @@ class FileAdminView extends File
}
}
if (in_array($file->upload_target_type, ['doc', 'com']))
if (in_array($file->upload_target_type, ['doc', 'com', 'ev:doc', 'ev:com']))
{
$var = $file->upload_target_type . '_srls';
$var = str_replace('ev:', '', $file->upload_target_type) . '_srls';
if (!in_array($target_srl, $$var))
{
$$var[] = $target_srl;
@ -187,7 +187,7 @@ class FileAdminView extends File
foreach($file_list as $srl => $file)
{
if($file->upload_target_type == 'com')
if($file->upload_target_type === 'com' || $file->upload_target_type === 'ev:com')
{
$file_list[$srl]->target_document_srl = $comment_list[$file->upload_target_srl]->document_srl;
}

View file

@ -472,9 +472,12 @@ class FileModel extends File
*
* @return object Returns a file configuration of current module. If user is admin, returns PHP's max file size and allow all file types.
*/
public static function getUploadConfig()
public static function getUploadConfig($module_srl = 0)
{
$module_srl = Context::get('module_srl') ?: (Context::get('current_module_info')->module_srl ?? 0);
if (!$module_srl)
{
$module_srl = Context::get('module_srl') ?: (Context::get('current_module_info')->module_srl ?? 0);
}
$config = self::getFileConfig($module_srl);
if (Rhymix\Framework\Session::isAdmin())
{

View file

@ -57,12 +57,12 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';
<!--@foreach($file_list as $no => $val)-->
<!-- one document start -->
<!--@if($val->upload_target_srl != $cur_upload_target_srl)-->
<!--@if($val->upload_target_type == 'com')-->
<!--@if(in_array($val->upload_target_type, ['com', 'ev:com']))-->
{@ $document_srl = $val->target_document_srl}
{@ $move_uri = getUrl('', 'document_srl', $document_srl).'#comment_'.$val->upload_target_srl}
<!--@elseif($val->upload_target_type == 'doc')-->
<!--@elseif(in_array($val->upload_target_type, ['doc', 'ev:doc']))-->
{@ $document_srl = $val->upload_target_srl}
{@ $move_uri = getUrl('', 'document_srl', $document_srl)}
{@ $move_uri = getUrl('', 'mid', $module_list[$val->module_srl]->mid, 'document_srl', $document_srl)}
<!--@end-->
{@ $cur_upload_target_srl = $val->upload_target_srl}
<tr>
@ -78,12 +78,12 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';
<!--@if($val->upload_target_type == 'mod')-->[{$lang->module}] <!--@end-->
<!--@if($val->upload_target_type == 'msg')-->[{$lang->member_message}] <!--@end-->
<!--@if($val->upload_target_type == 'doc' && $document_list[$document_srl] && $document_list[$document_srl]->get('module_srl') == $document_list[$document_srl]->get('member_srl'))-->[{$lang->cmd_temp_save}] <!--@end-->
<!--@if($val->upload_target_type == 'doc' && $document_list[$document_srl] && $document_list[$document_srl]->get('module_srl') == 0)-->[{$lang->cmd_trash}] <!--@end-->
<!--@if(preg_match('/^(?:ev:)?doc$/', $val->upload_target_type) && $document_list[$document_srl] && $document_list[$document_srl]->get('module_srl') == $document_list[$document_srl]->get('member_srl'))-->[{$lang->cmd_temp_save}] <!--@end-->
<!--@if(preg_match('/^(?:ev:)?doc$/', $val->upload_target_type) && $document_list[$document_srl] && $document_list[$document_srl]->get('module_srl') == 0)-->[{$lang->cmd_trash}] <!--@end-->
<!--@if($val->module_srl && isset($module_list[$val->module_srl]))-->
<a href="{getUrl('', 'mid', $module_list[$val->module_srl]->mid)}" target="_blank">{$module_list[$val->module_srl]->browser_title}</a>
<!--@end-->
<!--@if($document_list[$document_srl] && ($val->upload_target_type == 'doc' || $val->upload_target_type == 'com'))-->
<!--@if($document_list[$document_srl] && preg_match('/^(?:ev:)?(?:doc|com)$/', $val->upload_target_type))-->
- <!--@if($document_list[$document_srl]->get('module_srl') != $document_list[$document_srl]->get('member_srl'))--><a href="{$move_uri}" target="_blank">{$document_list[$document_srl]->getTitle()}</a><!--@else-->{$document_list[$document_srl]->getTitle()}<!--@end-->
<!--@end-->
<!--@end-->
@ -97,7 +97,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';
<!--@elseif($val->thumbnail_filename)-->
<img src="{$val->thumbnail_filename}" style="width:50px;height:50px;object-fit:cover;margin-right:4px">
<!--@end-->
<a href="{htmlspecialchars_decode($val->download_url)}">{htmlspecialchars($val->source_filename, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)}</a></td>
<a href="{$val->download_url}">{escape($val->source_filename, false)}</a></td>
<td class="nowr">{FileHandler::filesize($val->file_size)}</td>
<td class="nowr">{$val->download_count}</td>
<td class="nowr">

View file

@ -307,6 +307,10 @@ class MemberAdminModel extends Member
$id_list = implode(',',$list);
Context::set('id_list',$id_list);
$extravar_types = lang('common.column_type_list');
unset($extravar_types['file']);
Context::set('extravar_types', $extravar_types);
$oTemplate = TemplateHandler::getInstance();
$tpl = $oTemplate->compile($this->module_path.'tpl', 'insert_join_form');

View file

@ -22,7 +22,7 @@
<label for="columnType" class="x_control-label"><em style="color:red">*</em> {$lang->column_type}</label>
<div class="x_controls">
<select id="columnType" class="typeSelect" name="column_type">
<option loop="$lang->column_type_list=>$key,$type_info" value="{$key}" selected="selected"|cond="$formInfo->column_type == $key" >{$lang->column_type_list[$key]}</option>
<option loop="$extravar_types=>$key,$type_info" value="{$key}" selected="selected"|cond="$formInfo->column_type == $key" >{$lang->column_type_list[$key]}</option>
</select>
</div>
</div>

View file

@ -97,7 +97,11 @@ $lang->about_mobile_page_count = 'You can set the number of page links to move p
$lang->about_admin_id = 'You can grant someone permission to manage this module. Please enter the user ID or email address of the person you wish to add.';
$lang->about_grant_deatil = 'Registered users mean users who signed-up to the virtual sites (e.g., cafeXE).';
$lang->about_module = 'Rhymix consists of modules except the basic library. [Module Manage] module will show all installed modules and help you to manage them.';
$lang->about_extra_vars_default_value = 'If you need to provide multiple choices, you can separate them with a comma.';
$lang->extra_vars_is_strict = 'Specified values only';
$lang->extra_vars_options = 'Options';
$lang->about_extra_vars_is_strict = 'In single and multiple choice fields, only allow the values specified below. If you change the allowed values, it may affect previous posts.';
$lang->about_extra_vars_default_value = 'In single and multiple choice fields, the default value should be one of the values specified below.';
$lang->about_extra_vars_options = 'In single and multiple choice fields, please enter the options one in each line.';
$lang->about_search_virtual_site = 'Enter domain of virtual sites. To search modules of non-virtual site, search with blank';
$lang->about_extra_vars_eid_value = 'This is the unique ID for this field.<br>You can use a combination of Latin alphabets, numbers and underscore(_), as long as it starts with an alphabet.';
$lang->about_extra_vars_column_name = 'This is the name that is actually shown to users.';

View file

@ -96,7 +96,11 @@ $lang->about_mobile_page_count = '목록 하단, 페이지를 이동하는 링
$lang->about_admin_id = '특정 회원에게 이 모듈의 관리 권한을 부여할 수 있습니다. 권한을 부여할 회원의 아이디 또는 이메일 주소를 입력해 주세요.';
$lang->about_grant_deatil = '가입한 사용자는 cafeXE 등 분양형 가상 사이트에 가입을 한 로그인 사용자를 의미합니다.';
$lang->about_module = 'Rhymix는 기본 라이브러리를 제외한 나머지는 모두 모듈로 구성되어 있습니다. 모듈 관리 모듈은 설치된 모든 모듈을 보여주고 관리를 돕습니다.';
$lang->about_extra_vars_default_value = '다중/단일 선택 등 여러 선택지가 주어지는 경우 &#39;,&#39;(쉼표)로 구분하면 됩니다.';
$lang->extra_vars_is_strict = '임의입력 금지';
$lang->extra_vars_options = '선택지';
$lang->about_extra_vars_is_strict = '단일/다중 선택에서 미리 주어진 선택지만 입력할 수 있도록 합니다. 선택지를 변경할 경우 기존 게시물에 영향을 줄 수 있습니다.';
$lang->about_extra_vars_default_value = '단일/다중 선택의 경우, 아래에 입력한 선택지 중 하나여야 합니다.';
$lang->about_extra_vars_options = '단일/다중 선택 등 여러 선택지가 주어지는 경우, 한 줄에 하나씩 입력하십시오.<br><span style="color:red">구 버전과 달리, 쉼표로 구분하지 않으니 주의하십시오.</span>';
$lang->about_search_virtual_site = '가상 사이트(예:cafeXE) 도메인을 입력한 후 검색하세요. 가상 사이트 이외의 모듈은 내용을 비우고 검색하면 됩니다. (http:// 는 제외)';
$lang->about_extra_vars_eid_value = '시스템 내에서 이 변수를 식별하기 위한 ID값입니다. 예: school<br>영문, 숫자, _를 조합해서 사용할 수 있으며 첫 글자는 영문이어야 합니다.';
$lang->about_extra_vars_column_name = '사용자에게 보여지는 입력 항목 이름입니다. 예: 학교';