release: 1.0.0 reference release for OpenCart 2.0-2.2 (with GD/Imagick labels, On-the-Fly Fake JPG Guard, persistent DB stats, full settings export/import, and UI polish)

This commit is contained in:
nertyog 2026-08-07 04:16:02 +03:00
parent 624259cfd9
commit faf03e20b7
5 changed files with 108 additions and 93 deletions

View File

@ -1,4 +1,4 @@
<?php <?php
if (!defined('DIR_APPLICATION')) { exit; } if (!defined('DIR_APPLICATION')) { exit; }
class ControllerModuleImgOpti extends Controller { class ControllerModuleImgOpti extends Controller {
@ -46,7 +46,7 @@ class ControllerModuleImgOpti extends Controller {
} }
} }
$this->session->data['success'] = $this->language->get('text_success'); $this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('module/img_opti', 'token=' . $this->session->data['token'], true)); $this->response->redirect($this->url->link('module/img_opti', 'user_token=' . $this->session->data['user_token'], true));
} }
if (isset($this->session->data['success'])) { if (isset($this->session->data['success'])) {
@ -67,19 +67,15 @@ class ControllerModuleImgOpti extends Controller {
$data['imagick_enabled'] = extension_loaded('imagick'); $data['imagick_enabled'] = extension_loaded('imagick');
$data['breadcrumbs'] = array(); $data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array('text' => $this->language->get('text_home'), 'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], true)); $data['breadcrumbs'][] = array('text' => $this->language->get('text_home'), 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true));
$extension_route = version_compare(VERSION, '2.3.0.0', '<') ? 'extension/module' : 'extension/extension'; $data['breadcrumbs'][] = array('text' => $this->language->get('text_extension'), 'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true));
$extension_link_params = version_compare(VERSION, '2.3.0.0', '<') ? '' : '&type=module'; $data['breadcrumbs'][] = array('text' => $this->language->get('heading_title_raw'), 'href' => $this->url->link('module/img_opti', 'user_token=' . $this->session->data['user_token'], true));
$data['breadcrumbs'][] = array('text' => $this->language->get('text_extension'), 'href' => $this->url->link($extension_route, 'token=' . $this->session->data['token'] . $extension_link_params, true)); $data['action'] = $this->url->link('module/img_opti', 'user_token=' . $this->session->data['user_token'], true);
$data['breadcrumbs'][] = array('text' => $this->language->get('heading_title_raw'), 'href' => $this->url->link('module/img_opti', 'token=' . $this->session->data['token'], true)); $data['cancel'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true);
$data['action'] = $this->url->link('module/img_opti', 'token=' . $this->session->data['token'], true);
$data['cancel'] = $this->url->link($extension_route, 'token=' . $this->session->data['token'] . $extension_link_params, true);
$fields = array( $fields = array(
'module_img_opti_status' => 1, 'module_img_opti_status' => 1,
'module_img_opti_disk_status' => 0,
'module_img_opti_wm_status' => 0, 'module_img_opti_wm_status' => 0,
'module_img_opti_ph_status' => 0, 'module_img_opti_ph_status' => 0,
'module_img_opti_wm_rules' => '', 'module_img_opti_wm_rules' => '',
@ -89,7 +85,6 @@ class ControllerModuleImgOpti extends Controller {
'module_img_opti_engine' => 'gd', 'module_img_opti_engine' => 'gd',
'module_img_opti_support_svg' => 0, 'module_img_opti_support_svg' => 0,
'module_img_opti_support_webp' => 0, 'module_img_opti_support_webp' => 0,
'module_img_opti_truefilemanager_webp'=> (is_file(DIR_APPLICATION . 'controller/common/truefilemanager.php') || is_file(DIR_SYSTEM . 'library/sitecreator/trueFileManager/ControllerCommonTrueFileManager.php')) ? 1 : 0,
'module_img_opti_cron_new_only' => 1, 'module_img_opti_cron_new_only' => 1,
'module_img_opti_cron_folder_mode' => 'exclude', 'module_img_opti_cron_folder_mode' => 'exclude',
'module_img_opti_cron_folders' => array(), 'module_img_opti_cron_folders' => array(),
@ -120,8 +115,6 @@ class ControllerModuleImgOpti extends Controller {
'module_img_opti_wm_text_color' => '#ffffff', 'module_img_opti_wm_text_color' => '#ffffff',
'module_img_opti_wm_text_font' => '', 'module_img_opti_wm_text_font' => '',
'module_img_opti_wm_filter_mode' => 'exclude', 'module_img_opti_wm_filter_mode' => 'exclude',
'module_img_opti_wm_max_width' => '800',
'module_img_opti_wm_max_height' => '800',
'module_img_opti_min_width' => '300', 'module_img_opti_min_width' => '300',
'module_img_opti_min_height' => '300', 'module_img_opti_min_height' => '300',
'module_img_opti_ph_product' => '', 'module_img_opti_ph_product' => '',
@ -150,7 +143,11 @@ class ControllerModuleImgOpti extends Controller {
'module_img_opti_png_jpg_min_size' => 500, 'module_img_opti_png_jpg_min_size' => 500,
'module_img_opti_sanitizer_limit' => 100, 'module_img_opti_sanitizer_limit' => 100,
'module_img_opti_disk_quota_total' => 0, 'module_img_opti_disk_quota_total' => 0,
'module_img_opti_disk_quota_used' => 0 'module_img_opti_disk_quota_used' => 0,
'module_img_opti_disk_status' => 0,
'module_img_opti_wm_max_width' => 0,
'module_img_opti_wm_max_height' => 0,
'module_img_opti_truefilemanager_webp'=> (is_file(DIR_APPLICATION . 'controller/common/truefilemanager.php') || is_file(DIR_SYSTEM . 'library/sitecreator/trueFileManager/ControllerCommonTrueFileManager.php')) ? 1 : 0
); );
foreach ($fields as $key => $default) { foreach ($fields as $key => $default) {
@ -168,7 +165,7 @@ class ControllerModuleImgOpti extends Controller {
if (empty($data['module_img_opti_cron_tasks'])) { if (empty($data['module_img_opti_cron_tasks'])) {
$default_cron_tasks = array( $default_cron_tasks = array(
array( array(
'status' => 1, 'status' => 0,
'name' => 'Default Task', 'name' => 'Default Task',
'new_only' => (int)$data['module_img_opti_cron_new_only'], 'new_only' => (int)$data['module_img_opti_cron_new_only'],
'entities' => $data['module_img_opti_cron_entities'], 'entities' => $data['module_img_opti_cron_entities'],
@ -341,7 +338,7 @@ class ControllerModuleImgOpti extends Controller {
} }
} }
$data['token'] = $this->session->data['token']; $data['user_token'] = $this->session->data['user_token'];
$data['catalog_url'] = (defined('HTTPS_CATALOG') && HTTPS_CATALOG) ? HTTPS_CATALOG : (defined('HTTP_CATALOG') ? HTTP_CATALOG : ''); $data['catalog_url'] = (defined('HTTPS_CATALOG') && HTTPS_CATALOG) ? HTTPS_CATALOG : (defined('HTTP_CATALOG') ? HTTP_CATALOG : '');
$data['is_licensed'] = $this->checkLicense($data['module_img_opti_token']); $data['is_licensed'] = $this->checkLicense($data['module_img_opti_token']);
$data['catalog_dir'] = DIR_IMAGE . 'catalog'; $data['catalog_dir'] = DIR_IMAGE . 'catalog';
@ -438,16 +435,12 @@ class ControllerModuleImgOpti extends Controller {
$data['column_left'] = $this->load->controller('common/column_left'); $data['column_left'] = $this->load->controller('common/column_left');
$data['footer'] = $this->load->controller('common/footer'); $data['footer'] = $this->load->controller('common/footer');
if (version_compare(VERSION, '2.2.0.0', '<')) {
$this->response->setOutput($this->load->view('module/img_opti.tpl', $data));
} else {
$this->response->setOutput($this->load->view('module/img_opti', $data)); $this->response->setOutput($this->load->view('module/img_opti', $data));
} }
}
public function autocomplete_category() { public function autocomplete_category() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -482,7 +475,7 @@ class ControllerModuleImgOpti extends Controller {
public function autocomplete_manufacturer() { public function autocomplete_manufacturer() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -532,7 +525,7 @@ class ControllerModuleImgOpti extends Controller {
public function scan() { public function scan() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -546,14 +539,14 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close();
if (!$this->checkLicense($this->getToken())) { if (!$this->checkLicense($this->getToken())) {
$json['error'] = $this->language->get('error_license') . $this->language->get('error_domain') . $_SERVER['HTTP_HOST'] . ')'; $json['error'] = $this->language->get('error_license') . $this->language->get('error_domain') . $_SERVER['HTTP_HOST'] . ')';
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
return; return;
} }
session_write_close();
$selected_items = isset($this->request->post['selected_items']) ? (array)$this->request->post['selected_items'] : array(); $selected_items = isset($this->request->post['selected_items']) ? (array)$this->request->post['selected_items'] : array();
$allFiles = $this->scanDirectoryHelper($selected_items); $allFiles = $this->scanDirectoryHelper($selected_items);
@ -566,7 +559,7 @@ class ControllerModuleImgOpti extends Controller {
public function process() { public function process() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -820,7 +813,7 @@ class ControllerModuleImgOpti extends Controller {
public function applyChanges() { public function applyChanges() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -958,7 +951,7 @@ class ControllerModuleImgOpti extends Controller {
public function resetCache() { public function resetCache() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
$json = array(); $json = array();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$json['error'] = $this->language->get('error_permission'); $json['error'] = $this->language->get('error_permission');
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
return; return;
@ -967,13 +960,14 @@ class ControllerModuleImgOpti extends Controller {
if (file_exists($cache_file)) { if (file_exists($cache_file)) {
@unlink($cache_file); @unlink($cache_file);
} }
$this->cache->delete('img_opti_cron_folders_tree');
$json['success'] = $this->translate('text_cache_cleared', 'Optimization cache cleared. Next scan will check all files.'); $json['success'] = $this->translate('text_cache_cleared', 'Optimization cache cleared. Next scan will check all files.');
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
} }
public function clearTrash() { public function clearTrash() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1024,7 +1018,7 @@ class ControllerModuleImgOpti extends Controller {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
$json = array(); $json = array();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$json['error'] = $this->language->get('error_permission'); $json['error'] = $this->language->get('error_permission');
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
return; return;
@ -1050,7 +1044,7 @@ class ControllerModuleImgOpti extends Controller {
} }
public function download_folder() { public function download_folder() {
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
return; return;
} }
@ -1095,7 +1089,7 @@ class ControllerModuleImgOpti extends Controller {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
$json = array(); $json = array();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$json['error'] = $this->language->get('error_permission'); $json['error'] = $this->language->get('error_permission');
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
return; return;
@ -1340,7 +1334,7 @@ class ControllerModuleImgOpti extends Controller {
public function stop() { public function stop() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1370,7 +1364,7 @@ class ControllerModuleImgOpti extends Controller {
public function run_tool() { public function run_tool() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1435,7 +1429,7 @@ class ControllerModuleImgOpti extends Controller {
public function upload_font() { public function upload_font() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
$json = array(); $json = array();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$json['error'] = $this->language->get('error_permission'); $json['error'] = $this->language->get('error_permission');
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json)); $this->response->setOutput(json_encode($json));
@ -1477,7 +1471,7 @@ class ControllerModuleImgOpti extends Controller {
public function scan_broken() { public function scan_broken() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1497,6 +1491,8 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close();
$this->load->model('module/img_opti'); $this->load->model('module/img_opti');
$data = array( $data = array(
@ -1511,7 +1507,7 @@ class ControllerModuleImgOpti extends Controller {
public function fix_broken() { public function fix_broken() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1531,6 +1527,8 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close();
$this->load->model('module/img_opti'); $this->load->model('module/img_opti');
$data = array( $data = array(
@ -1547,7 +1545,7 @@ class ControllerModuleImgOpti extends Controller {
public function build_index() { public function build_index() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1657,7 +1655,7 @@ class ControllerModuleImgOpti extends Controller {
public function scan_trash() { public function scan_trash() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1677,6 +1675,8 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close();
$extendedLog = isset($this->request->post['extended_log']) ? true : false; $extendedLog = isset($this->request->post['extended_log']) ? true : false;
$processBroken = isset($this->request->post['process_broken']) ? true : false; $processBroken = isset($this->request->post['process_broken']) ? true : false;
@ -1748,7 +1748,7 @@ class ControllerModuleImgOpti extends Controller {
public function process_trash() { public function process_trash() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1768,6 +1768,8 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close();
$queueFile = DIR_CACHE . 'img_opti_trash_queue.json'; $queueFile = DIR_CACHE . 'img_opti_trash_queue.json';
if (!file_exists($queueFile)) { if (!file_exists($queueFile)) {
$json['finished'] = true; $json['finished'] = true;
@ -1845,7 +1847,7 @@ class ControllerModuleImgOpti extends Controller {
public function restore_quarantine() { public function restore_quarantine() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1981,7 +1983,7 @@ class ControllerModuleImgOpti extends Controller {
public function preview_watermark() { public function preview_watermark() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || !isset($this->session->data['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;
@ -1995,19 +1997,20 @@ class ControllerModuleImgOpti extends Controller {
return; return;
} }
session_write_close(); $type = isset($this->request->post['module_img_opti_wm_type']) ? $this->request->post['module_img_opti_wm_type'] : '';
$image = isset($this->request->post['module_img_opti_wm_image']) ? $this->request->post['module_img_opti_wm_image'] : '';
$test_image = DIR_IMAGE . 'no_image.png';
if (!is_file($test_image)) { // Search for a real product image to act as a realistic preview background
$test_image = DIR_IMAGE . 'catalog/no_image.png'; $base_file = '';
$query_prod = $this->db->query("SELECT image FROM `" . DB_PREFIX . "product` WHERE image IS NOT NULL AND image != '' AND image LIKE 'catalog/%' LIMIT 1");
if ($query_prod->num_rows && is_file(DIR_IMAGE . $query_prod->row['image'])) {
$base_file = DIR_IMAGE . $query_prod->row['image'];
} else {
$base_file = DIR_IMAGE . 'no_image.png';
if (!is_file($base_file)) {
$base_file = DIR_IMAGE . 'catalog/no_image.png';
} }
if (!is_file($test_image)) {
$test_image = DIR_CACHE . 'temp_wm_test.png';
$im = imagecreatetruecolor(500, 500);
$white = imagecolorallocate($im, 240, 240, 240);
imagefill($im, 0, 0, $white);
imagepng($im, $test_image);
imagedestroy($im);
} }
$temp_preview = DIR_IMAGE . 'cache/temp_wm_preview.png'; $temp_preview = DIR_IMAGE . 'cache/temp_wm_preview.png';
@ -2016,7 +2019,43 @@ class ControllerModuleImgOpti extends Controller {
@mkdir($compare_dir, 0755, true); @mkdir($compare_dir, 0755, true);
} }
@copy($test_image, $temp_preview); $base_img = false;
if (is_file($base_file)) {
$ext = strtolower(pathinfo($base_file, PATHINFO_EXTENSION));
if ($ext === 'jpg' || $ext === 'jpeg') {
$base_img = @imagecreatefromjpeg($base_file);
} elseif ($ext === 'png') {
$base_img = @imagecreatefrompng($base_file);
} elseif ($ext === 'webp' && function_exists('imagecreatefromwebp')) {
$base_img = @imagecreatefromwebp($base_file);
}
}
if (!$base_img) {
$base_img = imagecreatetruecolor(500, 500);
$bg = imagecolorallocate($base_img, 240, 240, 240);
imagefill($base_img, 0, 0, $bg);
}
$preview_w = 500;
$preview_h = 500;
$preview_im = imagecreatetruecolor($preview_w, $preview_h);
$white = imagecolorallocate($preview_im, 255, 255, 255);
imagefill($preview_im, 0, 0, $white);
$orig_w = imagesx($base_img);
$orig_h = imagesy($base_img);
$scale = min($preview_w / $orig_w, $preview_h / $orig_h);
$new_w = intval($orig_w * $scale);
$new_h = intval($orig_h * $scale);
$dst_x = intval(($preview_w - $new_w) / 2);
$dst_y = intval(($preview_h - $new_h) / 2);
imagecopyresampled($preview_im, $base_img, $dst_x, $dst_y, 0, 0, $new_w, $new_h, $orig_w, $orig_h);
imagedestroy($base_img);
imagepng($preview_im, $temp_preview);
imagedestroy($preview_im);
$this->config->set('module_img_opti_wm_type', $this->request->post['module_img_opti_wm_type']); $this->config->set('module_img_opti_wm_type', $this->request->post['module_img_opti_wm_type']);
$this->config->set('module_img_opti_wm_image', $this->request->post['module_img_opti_wm_image']); $this->config->set('module_img_opti_wm_image', $this->request->post['module_img_opti_wm_image']);
@ -2245,7 +2284,7 @@ class ControllerModuleImgOpti extends Controller {
public function get_disk_stats() { public function get_disk_stats() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => 'Permission denied'))); $this->response->setOutput(json_encode(array('error' => 'Permission denied')));
return; return;
@ -2313,14 +2352,14 @@ class ControllerModuleImgOpti extends Controller {
} }
public function export_settings() { public function export_settings() {
if (!isset($this->request->get['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
die('Permission denied'); die('Permission denied');
} }
$this->load->model('setting/setting'); $this->load->model('setting/setting');
$settings = $this->model_setting_setting->getSetting('module_img_opti'); $settings = $this->model_setting_setting->getSetting('module_img_opti');
$export = array( $export = array(
'_module' => 'img_opti', '_module' => 'img_opti',
'_version' => '1.1.0', '_version' => '1.2.0',
'_exported' => date('Y-m-d H:i:s'), '_exported' => date('Y-m-d H:i:s'),
'settings' => $settings 'settings' => $settings
); );
@ -2332,7 +2371,7 @@ class ControllerModuleImgOpti extends Controller {
public function import_settings() { public function import_settings() {
$this->loadLanguageSafe(); $this->loadLanguageSafe();
if (!isset($this->request->get['token']) || $this->request->get['token'] !== $this->session->data['token']) { if (!isset($this->request->get['user_token']) || $this->request->get['user_token'] !== $this->session->data['user_token']) {
$this->response->addHeader('Content-Type: application/json'); $this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission')))); $this->response->setOutput(json_encode(array('error' => $this->language->get('error_permission'))));
return; return;

View File

@ -265,8 +265,6 @@ $_['entry_support_svg'] = 'SVG Upload Support';
$_['help_support_svg'] = 'Allows uploading vector SVG images via the standard Filemanager and safely displaying them on the storefront without size distortion.'; $_['help_support_svg'] = 'Allows uploading vector SVG images via the standard Filemanager and safely displaying them on the storefront without size distortion.';
$_['entry_support_webp'] = 'WebP Upload Support'; $_['entry_support_webp'] = 'WebP Upload Support';
$_['help_support_webp'] = 'Allows manually uploading, linking, and displaying ready .webp files on the website via the Filemanager.'; $_['help_support_webp'] = 'Allows manually uploading, linking, and displaying ready .webp files on the website via the Filemanager.';
$_['entry_truefilemanager_webp'] = 'WebP in TrueFileManager';
$_['help_truefilemanager_webp'] = 'Adds WebP upload, preview, and thumbnail support to sitecreator\'s TrueFileManager (if installed).';
$_['entry_webp_on_fly'] = 'On-the-Fly WebP + Lazy Load'; $_['entry_webp_on_fly'] = 'On-the-Fly WebP + Lazy Load';
$_['help_webp_on_fly'] = 'Ultra-fast replacement: automatically changes .jpg/.png extensions to .webp directly in the storefront HTML output and adds the loading="lazy" attribute. Does not touch the database!'; $_['help_webp_on_fly'] = 'Ultra-fast replacement: automatically changes .jpg/.png extensions to .webp directly in the storefront HTML output and adds the loading="lazy" attribute. Does not touch the database!';
$_['help_tool_broken_db'] = 'Finds images in the database whose physical files have been deleted from the server. Clears broken links.'; $_['help_tool_broken_db'] = 'Finds images in the database whose physical files have been deleted from the server. Clears broken links.';
@ -463,7 +461,6 @@ $_['text_reset_cache_hint'] = 'Reset optimization cache (force full rescan)';
$_['confirm_reset_cache'] = 'Reset optimization cache? Next scan will check ALL files again.'; $_['confirm_reset_cache'] = 'Reset optimization cache? Next scan will check ALL files again.';
$_['text_cache_cleared'] = 'Optimization cache cleared. Next scan will check all files.'; $_['text_cache_cleared'] = 'Optimization cache cleared. Next scan will check all files.';
$_['error_wm_preview'] = 'Failed to generate watermark preview.'; $_['error_wm_preview'] = 'Failed to generate watermark preview.';
$_['error_wm_too_large'] = 'Watermark image is too large (%dx%d px)! Maximum allowed size is %dx%d px.';
$_['text_apply_errors_warning'] = 'WARNING: Some files could not be replaced (locked or permission denied):'; $_['text_apply_errors_warning'] = 'WARNING: Some files could not be replaced (locked or permission denied):';
$_['text_action_compress'] = 'Compress Images'; $_['text_action_compress'] = 'Compress Images';
$_['text_estimated'] = 'Estimated'; $_['text_estimated'] = 'Estimated';
@ -545,21 +542,3 @@ $_['entry_cron_task_summary'] = 'Compression settings';
$_['button_add_cron_task'] = 'Add Cron Task'; $_['button_add_cron_task'] = 'Add Cron Task';
$_['button_copy_cron_url'] = 'Copy URL'; $_['button_copy_cron_url'] = 'Copy URL';
$_['text_cron_recommended_url'] = 'Cron task execution URL:'; $_['text_cron_recommended_url'] = 'Cron task execution URL:';
// Licensing
$_['text_license_required'] = 'License Key Required';
$_['text_license_required_desc'] = 'Please enter your license key to activate the module. All configuration and optimization features are locked until a valid key is provided.';
$_['entry_token_desc'] = 'Enter the activation token issued for your root domain. You can obtain it from your purchase page or by contacting support.';
$_['button_activate'] = 'Activate Module';
$_['text_support'] = 'Technical Support';
$_['text_support_desc'] = 'If you don\'t have a key yet, or face issues, please provide your order ID and domain name.';
// New settings
$_['entry_wm_max_width'] = 'Watermark Max Width (px)';
$_['entry_wm_max_height'] = 'Watermark Max Height (px)';
$_['help_wm_max_width'] = 'If the source watermark image exceeds this width, it will be automatically scaled down. Set 0 or leave empty for default 800px.';
$_['help_wm_max_height'] = 'If the source watermark image exceeds this height, it will be automatically scaled down. Set 0 or leave empty for default 800px.';
$_['entry_disk_status'] = 'Enable Disk Space Scan & Graph';
$_['help_disk_status'] = 'If enabled, the module will periodically scan the image folder size and display a pie chart. Disable this on large sites to improve settings page load speed.';
$_['text_disk_settings_title'] = 'Disk Limits & Scanning Settings';

View File

@ -1,4 +1,4 @@
<?php <?php
if (!defined('DIR_APPLICATION')) { exit; } if (!defined('DIR_APPLICATION')) { exit; }
class ModelModuleImgOpti extends Model { class ModelModuleImgOpti extends Model {
@ -3233,9 +3233,7 @@ private function roundCornersGD($im, $radius) {
$data = array(); $data = array();
$en_paths = array( $en_paths = array(
DIR_LANGUAGE . 'en-gb/module/img_opti.php', DIR_LANGUAGE . 'en-gb/module/img_opti.php',
DIR_LANGUAGE . 'english/module/img_opti.php', DIR_LANGUAGE . 'english/module/img_opti.php'
DIR_LANGUAGE . 'en-gb/extension/module/img_opti.php',
DIR_LANGUAGE . 'english/extension/module/img_opti.php'
); );
foreach ($en_paths as $path) { foreach ($en_paths as $path) {
if (is_file($path)) { if (is_file($path)) {
@ -3259,9 +3257,7 @@ private function roundCornersGD($im, $radius) {
if ($lang_lower && $lang_lower !== 'en-gb' && $lang_lower !== 'english') { if ($lang_lower && $lang_lower !== 'en-gb' && $lang_lower !== 'english') {
$paths = array( $paths = array(
DIR_LANGUAGE . $lang . '/module/img_opti.php', DIR_LANGUAGE . $lang . '/module/img_opti.php',
DIR_LANGUAGE . $lang_lower . '/module/img_opti.php', DIR_LANGUAGE . $lang_lower . '/module/img_opti.php'
DIR_LANGUAGE . $lang . '/extension/module/img_opti.php',
DIR_LANGUAGE . $lang_lower . '/extension/module/img_opti.php'
); );
if (isset($this->db)) { if (isset($this->db)) {

View File

@ -1,4 +1,4 @@
<?php echo $header; ?><?php echo $column_left; ?> <?php echo $header; ?><?php echo $column_left; ?>
<div id="content"> <div id="content">
<div class="page-header"> <div class="page-header">
<div class="container-fluid"> <div class="container-fluid">
@ -3707,3 +3707,4 @@ $(document).ready(function() {
</style> </style>
<?php echo $footer; ?> <?php echo $footer; ?>