diff --git a/modules/file/conf/module.xml b/modules/file/conf/module.xml index 4c5c5f598..fa7dac308 100644 --- a/modules/file/conf/module.xml +++ b/modules/file/conf/module.xml @@ -14,11 +14,14 @@ + + + diff --git a/modules/file/file.admin.controller.php b/modules/file/file.admin.controller.php index 5648eaa95..c8fb70f2f 100644 --- a/modules/file/file.admin.controller.php +++ b/modules/file/file.admin.controller.php @@ -296,6 +296,142 @@ class FileAdminController extends File else $_SESSION['file_management'][$output->file_srl] = true; } } + + /** + * Edit filename + */ + public function procFileAdminEditFileName() + { + $file_srl = Context::get('file_srl'); + if (!$file_srl) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + $file = FileModel::getFile($file_srl); + if (!$file) + { + throw new Rhymix\Framework\Exceptions\TargetNotFound; + } + $file_name = trim(utf8_normalize_spaces(utf8_clean(Context::get('file_name')))); + $file_name = Rhymix\Framework\Filters\FilenameFilter::clean($file_name); + if ($file_name === '') + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + + $output = executeQuery('file.updateFileName', [ + 'file_srl' => $file_srl, + 'source_filename' => $file_name, + ]); + if (!$output->toBool()) + { + return $output; + } + + $this->setMessage('success_updated'); + $this->setRedirectUrl(Context::get('success_return_url') ?: getNotEncodedUrl(['module' => 'admin', 'act' => 'dispFileAdminEdit', 'file_srl' => $file_srl])); + } + + /** + * Edit image + */ + public function procFileAdminEditImage() + { + $file_srl = Context::get('file_srl'); + if (!$file_srl) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + $file = FileModel::getFile($file_srl); + if (!$file) + { + throw new Rhymix\Framework\Exceptions\TargetNotFound; + } + + // Validate user input. + $width = intval(Context::get('new_width')); + $height = intval(Context::get('new_height')); + $format = Context::get('format'); + $quality = intval(Context::get('quality')); + if ($width <= 0 || $height <= 0 || !in_array($format, ['jpg', 'png', 'webp']) || $quality <= 0 || $quality > 100) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + + // Generate filenames. + $uploaded_filename = FileHandler::getRealPath($file->uploaded_filename); + $temp_filename = \RX_BASEDIR . 'files/cache/temp/' . Rhymix\Framework\Security::getRandom(32, 'hex') . '.' . $format; + $new_filename = preg_replace('/\.[a-z]+$/', '.' . $format, $file->source_filename); + $del_filename = null; + + // Should this file be moved from binaries to images? + if (str_starts_with($uploaded_filename, \RX_BASEDIR . 'files/attach/binaries/')) + { + $del_filename = $uploaded_filename; + $uploaded_filename = preg_replace('!/files/attach/binaries/!', '/files/attach/images/', $uploaded_filename, 1) . '.' . $format; + } + + // Resize the image using GD or ImageMagick. + $config = FileModel::getFileConfig(); + $result = FileHandler::createImageFile(FileHandler::getRealPath($file->uploaded_filename), $temp_filename, $width, $height, $format, 'fill', $quality); + if (!$result && !empty($config->magick_command)) + { + $command = vsprintf('%s %s -resize %dx%d -quality %d %s %s %s', [ + \RX_WINDOWS ? escapeshellarg($config->magick_command) : $config->magick_command, + escapeshellarg(FileHandler::getRealPath($file->uploaded_filename)), + $width, $height, $quality, + '-auto-orient -strip', + '-limit memory 64MB -limit map 128MB -limit disk 1GB', + escapeshellarg($temp_filename), + ]); + @exec($command, $output, $return_var); + $result = $return_var === 0 ? true : false; + } + + // If successfully resized, replace original file and update the image size in DB. + if ($result && Rhymix\Framework\Storage::exists($temp_filename) && filesize($temp_filename) > 0) + { + $moved = Rhymix\Framework\Storage::move($temp_filename, $uploaded_filename); + if (!$moved) + { + throw new Rhymix\Framework\Exception; + } + if ($del_filename) + { + Rhymix\Framework\Storage::delete($del_filename); + } + + clearstatcache(true, $uploaded_filename); + $filesize = filesize($uploaded_filename); + $relative_path = preg_replace('!^' . preg_quote(\RX_BASEDIR, '!') . '!', './', $uploaded_filename, 1); + + $updated = executeQuery('file.updateFile', [ + 'file_srl' => $file_srl, + 'module_srl' => $file->module_srl, + 'upload_target_srl' => $file->upload_target_srl, + 'source_filename' => $new_filename, + 'uploaded_filename' => $relative_path, + 'direct_download' => 'Y', + 'mime_type' => Rhymix\Framework\MIME::getTypeByFilename($new_filename), + 'original_type' => $file->original_type ?: $file->mime_type, + 'is_cover' => $file->cover_image, + 'file_size' => $filesize, + 'width' => $width, + 'height' => $height, + ]); + if (!$updated->toBool()) + { + return $updated; + } + } + else + { + throw new Rhymix\Framework\Exception; + } + + $this->setMessage('success_updated'); + $this->setRedirectUrl(Context::get('success_return_url') ?: getNotEncodedUrl(['module' => 'admin', 'act' => 'dispFileAdminEdit', 'file_srl' => $file_srl])); + } } /* End of file file.admin.controller.php */ /* Location: ./modules/file/file.admin.controller.php */ diff --git a/modules/file/file.admin.view.php b/modules/file/file.admin.view.php index f1b371e74..ff05e46bf 100644 --- a/modules/file/file.admin.view.php +++ b/modules/file/file.admin.view.php @@ -6,20 +6,12 @@ */ class FileAdminView extends File { - /** - * Initialization - * @return void - */ - function init() - { - } - /** * Display output list (for administrator) * * @return Object */ - function dispFileAdminList() + public function dispFileAdminList() { // Options to get a list $args = new stdClass(); @@ -213,11 +205,35 @@ class FileAdminView extends File } /** - * Upload config screen - * - * @return Object + * File edit screen */ - function dispFileAdminUploadConfig() + public function dispFileAdminEdit() + { + $file_srl = intval(Context::get('file_srl')); + if (!$file_srl) + { + throw new Rhymix\Framework\Exceptions\InvalidRequest; + } + $file = FileModel::getFile($file_srl); + if (!$file) + { + throw new Rhymix\Framework\Exceptions\TargetNotFound; + } + + $config = FileModel::getFileConfig(); + Context::set('config', $config); + Context::set('file', $file); + Context::set('is_ffmpeg', function_exists('exec') && !empty($config->ffmpeg_command) && Rhymix\Framework\Storage::isExecutable($config->ffmpeg_command) && !empty($config->ffprobe_command) && Rhymix\Framework\Storage::isExecutable($config->ffprobe_command)); + Context::set('is_magick', function_exists('exec') && !empty($config->magick_command) && Rhymix\Framework\Storage::isExecutable($config->magick_command)); + + $this->setTemplatePath($this->module_path . 'tpl'); + $this->setTemplateFile('file_edit'); + } + + /** + * Upload config screen + */ + public function dispFileAdminUploadConfig() { $oFileModel = getModel('file'); $config = $oFileModel->getFileConfig(); @@ -233,10 +249,8 @@ class FileAdminView extends File /** * Download config screen - * - * @return Object */ - function dispFileAdminDownloadConfig() + public function dispFileAdminDownloadConfig() { $oFileModel = getModel('file'); $config = $oFileModel->getFileConfig(); @@ -249,10 +263,8 @@ class FileAdminView extends File /** * Other config screen - * - * @return Object */ - function dispFileAdminOtherConfig() + public function dispFileAdminOtherConfig() { $oFileModel = getModel('file'); $config = $oFileModel->getFileConfig(); diff --git a/modules/file/lang/en.php b/modules/file/lang/en.php index 1fd6d25fd..2ef2b0c1d 100644 --- a/modules/file/lang/en.php +++ b/modules/file/lang/en.php @@ -132,3 +132,6 @@ $lang->msg_cannot_use_exec = 'The exec() function is disabled on this server.'; $lang->msg_cannot_use_ffmpeg = 'In order to use this feature, PHP must be able to execute \'ffmpeg\' and \'ffprobe\' commands.'; $lang->msg_cannot_use_exif = 'In order to use this feature, PHP must be installed with the \'exif\' extension.'; $lang->msg_need_magick = 'In order to handle AVIF and HEIC formats, PHP must be able to execute the \'magick\' command from ImageMagick 7.x or higher.'; +$lang->image_conversion = 'Image conversion'; +$lang->image_size = 'Image size'; +$lang->image_format = 'Image format'; diff --git a/modules/file/lang/ko.php b/modules/file/lang/ko.php index 192a2649f..57c6a7c67 100644 --- a/modules/file/lang/ko.php +++ b/modules/file/lang/ko.php @@ -135,3 +135,6 @@ $lang->msg_cannot_use_exec = '이 서버에서 exec() 함수를 사용할 수 $lang->msg_cannot_use_ffmpeg = '이 기능을 사용하려면 PHP에서 ffmpeg 및 ffprobe 명령을 실행할 수 있어야 합니다.'; $lang->msg_cannot_use_exif = '이 기능을 사용하려면 PHP exif 확장모듈이 필요합니다.'; $lang->msg_need_magick = 'AVIF, HEIC 변환을 위해서는 PHP에서 ImageMagick 7.x 이상의 magick 명령을 실행할 수 있어야 합니다.'; +$lang->image_conversion = '이미지 변환'; +$lang->image_size = '이미지 크기'; +$lang->image_format = '이미지 포맷'; diff --git a/modules/file/queries/updateFile.xml b/modules/file/queries/updateFile.xml index b9c0c06d3..16831fe17 100644 --- a/modules/file/queries/updateFile.xml +++ b/modules/file/queries/updateFile.xml @@ -3,11 +3,19 @@ + - + + + + + + + + diff --git a/modules/file/queries/updateFileName.xml b/modules/file/queries/updateFileName.xml new file mode 100644 index 000000000..86cd08415 --- /dev/null +++ b/modules/file/queries/updateFileName.xml @@ -0,0 +1,11 @@ + + +
+ + + + + + + + diff --git a/modules/file/tpl/css/config.css b/modules/file/tpl/css/config.css index 8dda1fea9..0e11eadd4 100644 --- a/modules/file/tpl/css/config.css +++ b/modules/file/tpl/css/config.css @@ -2,4 +2,8 @@ margin-top: -10px; border-bottom: 1px solid #ccc; background: #f5f5f5; -} \ No newline at end of file +} + +.x_help-block .preset_size { + font-size: 12px; +} diff --git a/modules/file/tpl/file_edit.html b/modules/file/tpl/file_edit.html new file mode 100644 index 000000000..cc135a155 --- /dev/null +++ b/modules/file/tpl/file_edit.html @@ -0,0 +1,83 @@ + + +
+

{$XE_VALIDATOR_MESSAGE}

+
+ +
+

{$XE_VALIDATOR_MESSAGE}

+
+ +
+

{$lang->file_name}

+
+ + + + +
+ +
+ +
+
+
+
+ +
+
+ +
+ + + + {@ list($file->width, $file->height) = getimagesize($file->uploaded_filename)} + + {@ $extension = strtolower($matches[1]); if ($extension === 'jpeg') $extension = 'jpg'; } +
+

{$lang->image_conversion}

+
+ + + + + + +
+ +
+ x + +

+ + + + + +

+
+
+
+ +
+ +
+
+
+ +
+ % +
+
+
+
+ +
+
+ +
+ diff --git a/modules/file/tpl/file_list.html b/modules/file/tpl/file_list.html index a4ca4a1d3..0d3e225f0 100644 --- a/modules/file/tpl/file_list.html +++ b/modules/file/tpl/file_list.html @@ -50,6 +50,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}';
+ @@ -66,7 +67,7 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {@ $cur_upload_target_srl = $val->upload_target_srl} - + diff --git a/modules/file/tpl/header.html b/modules/file/tpl/header.html index f2f294078..c0f8374b7 100644 --- a/modules/file/tpl/header.html +++ b/modules/file/tpl/header.html @@ -1,3 +1,4 @@ +
diff --git a/modules/file/tpl/js/file_admin.js b/modules/file/tpl/js/file_admin.js index aeba2bb22..f1a9e19d2 100644 --- a/modules/file/tpl/js/file_admin.js +++ b/modules/file/tpl/js/file_admin.js @@ -6,7 +6,7 @@ function getFileList() { var fileListTable = jQuery('#fileListTable'); var cartList = []; fileListTable.find(':checkbox[name=cart]').each(function(){ - if(this.checked) cartList.push(this.value); + if(this.checked) cartList.push(this.value); }); var params = new Array(); @@ -58,3 +58,24 @@ function checkSearch(form) } */ } + +(function() { + $(function() { + $('.preset_size').on('click', function() { + const preset_size = parseInt($(this).text(), 10); + const width = parseInt($('input[name=original_width]').val(), 10); + const height = parseInt($('input[name=original_height]').val(), 10); + let new_width = 0; + let new_height = 0; + if (width > height) { + new_width = preset_size; + new_height = Math.round(preset_size * (height / width)); + } else { + new_width = Math.round(preset_size * (width / height)); + new_height = preset_size; + } + $('input[name=new_width]').val(new_width); + $('input[name=new_height]').val(new_height); + }); + }); +})(jQuery);
{$lang->ipaddress} {$lang->status}{$lang->cmd_edit}
+ {$lang->is_valid} @@ -112,6 +113,9 @@ xe.lang.msg_empty_search_keyword = '{$lang->msg_empty_search_keyword}'; {zdate($val->regdate,"Y-m-d H:i")} {$val->ipaddress} {$lang->is_valid}{$lang->is_stand_by} + {$lang->cmd_edit} +