Image_Optimizer_NAT-2.0-2.2/install.xml

709 lines
42 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<modification>
<name>Image Optimizer [NAT]</name>
<id>Image_Optimizer_nat</id>
<code>img_opti_nat_v1</code>
<version>1.2.0</version>
<author>NAT</author>
<link>mailto:info@nat.od.ua</link>
<file path="admin/controller/common/column_left.php">
<operation error="skip">
<search><![CDATA[if ($this->user->hasPermission('access', 'catalog/product')) {]]></search>
<add position="before"><![CDATA[
$this->load->model('setting/setting');
if ($this->config->get('module_img_opti_status')) {
$nat_pos = $this->config->get('module_img_opti_menu_position');
if ($nat_pos == 'sidebar' || $nat_pos == 'both') {
if ($this->user->hasPermission('access', 'extension/module/img_opti')) {
$nat_item = array(
'name' => 'Image Optimizer',
'href' => $this->url->link('extension/module/img_opti', 'user_token=' . $this->session->data['user_token'], true),
'children' => array()
);
$nat_menu_index = -1;
if (isset($data['menus'])) {
foreach ($data['menus'] as $k => $menu) {
if (isset($menu['id']) && $menu['id'] == 'menu-nat') {
$nat_menu_index = $k;
break;
}
}
}
$exists = false;
if ($nat_menu_index > -1 && isset($data['menus'][$nat_menu_index]['children'])) {
foreach ($data['menus'][$nat_menu_index]['children'] as $child) {
if (isset($child['href']) && strpos($child['href'], 'route=extension/module/img_opti') !== false) {
$exists = true;
break;
}
}
}
if (!$exists) {
if ($nat_menu_index > -1) {
$data['menus'][$nat_menu_index]['children'][] = $nat_item;
} else {
$data['menus'][] = array(
'id' => 'menu-nat',
'icon' => 'fa-rocket fw',
'name' => '[NAT] Modules',
'href' => '',
'children' => array($nat_item)
);
}
}
}
}
}
]]></add>
</operation>
</file>
<file path="admin/controller/common/header.php">
<operation error="skip">
<search><![CDATA[$data['logout'] = $this->url->link('common/logout']]></search>
<add position="before"><![CDATA[
if (!isset($data['nat_menus'])) {
$data['nat_menus'] = array();
}
$this->load->model('setting/setting');
if ($this->config->get('module_img_opti_status')) {
$nat_pos = $this->config->get('module_img_opti_menu_position');
if ($nat_pos == 'header' || $nat_pos == 'both') {
if ($this->user->hasPermission('access', 'extension/module/img_opti')) {
$exists = false;
foreach ($data['nat_menus'] as $m) {
if (isset($m['href']) && strpos($m['href'], 'route=extension/module/img_opti') !== false) {
$exists = true;
break;
}
}
if (!$exists) {
$data['nat_menus'][] = array(
'name' => 'Image Optimizer',
'href' => $this->url->link('extension/module/img_opti', 'user_token=' . $this->session->data['user_token'], true)
);
}
}
}
}
]]></add>
</operation>
</file>
<file path="admin/view/template/common/header.twig">
<operation error="skip">
<search><![CDATA[</head>]]></search>
<add position="before"><![CDATA[
<style>
a.img-thumbnail img, a.thumbnail img {
width: 100px !important;
height: 100px !important;
object-fit: contain !important;
}
</style>
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[<li><a href="{{ logout }}"]]></search>
<add position="before"><![CDATA[
{% if nat_menus is defined and nat_menus and not nat_menu_rendered|default(false) %}
{% set nat_menu_rendered = true %}
<li class="dropdown" id="nat-ecosystem-menu">
<a class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-rocket fa-lg" style="color:#e74c3c;"></i> <span class="hidden-xs hidden-sm hidden-md">[NAT]</span> <span class="caret"></span></a>
<ul class="dropdown-menu dropdown-menu-right" id="nat-ecosystem-list">
<li class="dropdown-header">Ecosystem [NAT]</li>
{% for n_menu in nat_menus %}
<li><a href="{{ n_menu.href }}"><i class="fa fa-angle-right"></i> {{ n_menu.name }}</a></li>
{% endfor %}
</ul>
</li>
{% endif %}
]]></add>
</operation>
</file>
<file path="admin/controller/common/filemanager.php">
<operation error="skip">
<search><![CDATA[if (!in_array(utf8_strtolower(utf8_substr(strrchr($filename, '.'), 1)), $allowed)) {]]></search>
<add position="before"><![CDATA[
if ($this->config->get('module_img_opti_support_svg') && !in_array('svg', $allowed)) { $allowed[] = 'svg'; }
if ($this->config->get('module_img_opti_support_webp') && !in_array('webp', $allowed)) { $allowed[] = 'webp'; }
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if (!in_array($file['type'], $allowed)) {]]></search>
<add position="before"><![CDATA[
if ($this->config->get('module_img_opti_support_svg') && !in_array('image/svg+xml', $allowed)) { $allowed[] = 'image/svg+xml'; }
if ($this->config->get('module_img_opti_support_webp')) {
if (!in_array('image/webp', $allowed)) { $allowed[] = 'image/webp'; }
if (!in_array('image/vnd.webp', $allowed)) { $allowed[] = 'image/vnd.webp'; }
if (!in_array('image/x-webp', $allowed)) { $allowed[] = 'image/x-webp'; }
$uploaded_ext = utf8_strtolower(utf8_substr(strrchr($filename, '.'), 1));
if ($uploaded_ext === 'webp' && !in_array($file['type'], $allowed)) {
$allowed[] = $file['type'];
}
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[move_uploaded_file($file['tmp_name'], $directory . '/' . $filename);]]></search>
<add position="before"><![CDATA[
if (strtolower(substr(strrchr($filename, '.'), 1)) === 'svg') {
$svg_content = @file_get_contents($file['tmp_name']);
if ($svg_content) {
$svg_content = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svg_content);
$svg_content = preg_replace('/on\w+\s*=\s*["\'][^"\']*["\']/i', '', $svg_content);
$svg_content = preg_replace('/href\s*=\s*["\']\s*javascript:[^"\']*["\']/i', '', $svg_content);
@file_put_contents($file['tmp_name'], $svg_content);
}
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[$files = glob($directory . '/' . $filter_name . '*.{jpg,jpeg,png,gif,JPG,JPEG,PNG,GIF}', GLOB_BRACE);]]></search>
<add position="replace"><![CDATA[
$ext_list = array('jpg','jpeg','png','gif','JPG','JPEG','PNG','GIF');
if ($this->config->get('module_img_opti_support_svg')) {
$ext_list[] = 'svg'; $ext_list[] = 'SVG';
}
if ($this->config->get('module_img_opti_support_webp')) {
$ext_list[] = 'webp'; $ext_list[] = 'WEBP';
}
$files = glob($directory . '/' . $filter_name . '*.{' . implode(',', $ext_list) . '}', GLOB_BRACE);
]]></add>
</operation>
</file>
<file path="catalog/model/tool/image.php">
<operation error="skip">
<search><![CDATA[public function resize($filename, $width, $height) {]]></search>
<add position="after"><![CDATA[
$GLOBALS['registry'] = $this->registry;
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_auto_fake_jpg_guard') && !empty($filename)) {
$this->load->model('extension/module/img_opti');
try {
$filename = $this->model_extension_module_img_opti->checkAndFixFakeJpgOnTheFly($filename);
} catch (\Exception $e) {}
}
if (empty($filename) || ($filename !== 'no_image.png' && $filename !== 'placeholder.png' && !is_file(DIR_IMAGE . $filename))) {
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_broken_fallback')) {
$fallback_image = $this->config->get('module_img_opti_fallback_image');
if ($fallback_image && is_file(DIR_IMAGE . $fallback_image)) {
$filename = $fallback_image;
}
}
}
if (!empty($filename) && strpos($filename, '.') !== false) {
$nat_ext = strtolower(substr(strrchr($filename, '.'), 1));
if ($nat_ext === 'svg' || ($nat_ext === 'webp' && !function_exists('imagewebp'))) {
if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on' || ($this->request->server['HTTPS'] == '1')))) {
return $this->config->get('config_ssl') . 'image/' . str_replace('\\', '/', $filename);
} else {
return $this->config->get('config_url') . 'image/' . str_replace('\\', '/', $filename);
}
}
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if (!in_array($extension, array('jpg', 'jpeg', 'png', 'gif')))]]></search>
<add position="replace"><![CDATA[if (!in_array($extension, array('jpg', 'jpeg', 'png', 'gif', 'webp')))]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if (!in_array($image_type, array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF)))]]></search>
<add position="replace"><![CDATA[if (!in_array($image_type, array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, defined('IMAGETYPE_WEBP') ? IMAGETYPE_WEBP : 18)))]]></add>
</operation>
<operation error="skip">
<search><![CDATA[$image->save(DIR_IMAGE . $image_new);]]></search>
<add position="after"><![CDATA[
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_wm_status')) {
$this->load->model('extension/module/img_opti');
try {
$this->model_extension_module_img_opti->applyDynamicWatermark(DIR_IMAGE . $image_new, $filename);
} catch (\Exception $e) {}
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[copy(DIR_IMAGE . $image_old, DIR_IMAGE . $image_new);
}
}]]></search>
<add position="replace"><![CDATA[copy(DIR_IMAGE . $image_old, DIR_IMAGE . $image_new);
}
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_wm_status')) {
$this->load->model('extension/module/img_opti');
try {
$this->model_extension_module_img_opti->applyDynamicWatermark(DIR_IMAGE . $image_new, $filename);
} catch (\Exception $e) {}
}
}]]></add>
</operation>
</file>
<file path="admin/model/tool/image.php">
<operation error="skip">
<search><![CDATA[public function resize($filename, $width, $height) {]]></search>
<add position="after"><![CDATA[
$GLOBALS['registry'] = $this->registry;
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_auto_fake_jpg_guard') && !empty($filename)) {
$this->load->model('extension/module/img_opti');
try {
$filename = $this->model_extension_module_img_opti->checkAndFixFakeJpgOnTheFly($filename);
} catch (\Exception $e) {}
}
if (empty($filename) || ($filename !== 'no_image.png' && $filename !== 'placeholder.png' && !is_file(DIR_IMAGE . $filename))) {
if ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_broken_fallback')) {
$fallback_image = $this->config->get('module_img_opti_fallback_image');
if ($fallback_image && is_file(DIR_IMAGE . $fallback_image)) {
$filename = $fallback_image;
}
}
}
if (!empty($filename) && strpos($filename, '.') !== false) {
$nat_ext = strtolower(substr(strrchr($filename, '.'), 1));
if ($nat_ext === 'svg' || ($nat_ext === 'webp' && !function_exists('imagewebp'))) {
$nat_https = isset($this->request->server['HTTPS']) && ($this->request->server['HTTPS'] == 'on' || $this->request->server['HTTPS'] == '1');
$nat_base = $nat_https ? (defined('HTTPS_CATALOG') ? HTTPS_CATALOG : $this->config->get('config_ssl')) : (defined('HTTP_CATALOG') ? HTTP_CATALOG : $this->config->get('config_url'));
return $nat_base . 'image/' . str_replace('\\', '/', $filename);
}
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if (!in_array($extension, array('jpg', 'jpeg', 'png', 'gif')))]]></search>
<add position="replace"><![CDATA[if (!in_array($extension, array('jpg', 'jpeg', 'png', 'gif', 'webp')))]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if (!in_array($image_type, array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF)))]]></search>
<add position="replace"><![CDATA[if (!in_array($image_type, array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, defined('IMAGETYPE_WEBP') ? IMAGETYPE_WEBP : 18)))]]></add>
</operation>
</file>
<file path="system/library/image.php">
<operation>
<search><![CDATA[if ($this->mime == 'image/gif') {]]></search>
<add position="before"><![CDATA[
if (($this->mime == 'image/webp' || $this->mime == 'image/vnd.webp' || $this->mime == 'image/x-webp') && function_exists('imagecreatefromwebp')) {
$this->image = @imagecreatefromwebp($file);
} else
]]></add>
</operation>
<operation>
<search><![CDATA[if ($extension == 'jpeg' || $extension == 'jpg') {]]></search>
<add position="before"><![CDATA[
if ($extension == 'webp' && function_exists('imagewebp')) {
imagewebp($this->image, $file, $quality);
} else
]]></add>
</operation>
<operation>
<search><![CDATA[imagejpeg($this->image, $file, $quality);]]></search>
<add position="before"><![CDATA[
@imageinterlace($this->image, true);
]]></add>
</operation>
</file>
<file path="system/library/response.php">
<operation>
<search><![CDATA[echo $output;]]></search>
<add position="before"><![CDATA[
$registry = isset($GLOBALS['registry']) ? $GLOBALS['registry'] : null;
if ($registry && !defined('DIR_CATALOG')) {
$config = $registry->get('config');
if ($config && $config->get('module_img_opti_status')) {
$webp_on_fly = $config->get('module_img_opti_webp_on_fly');
$lazy_load = $config->get('module_img_opti_lazy_load');
$broken_fallback = $config->get('module_img_opti_broken_fallback');
$fallback_image = $config->get('module_img_opti_fallback_image');
$support_svg = $config->get('module_img_opti_support_svg');
$support_svg_autofix = ($config->get('module_img_opti_support_svg_autofix') !== null) ? $config->get('module_img_opti_support_svg_autofix') : 1;
$theme = $config->get('config_theme');
$additional_width = 0;
$additional_height = 0;
$thumb_width = 0;
$thumb_height = 0;
if ($theme) {
$additional_width = $config->get('theme_' . $theme . '_image_additional_width');
$additional_height = $config->get('theme_' . $theme . '_image_additional_height');
$thumb_width = $config->get('theme_' . $theme . '_image_thumb_width');
$thumb_height = $config->get('theme_' . $theme . '_image_thumb_height');
}
if (!$additional_width) { $additional_width = $config->get('theme_default_image_additional_width'); }
if (!$additional_height) { $additional_height = $config->get('theme_default_image_additional_height'); }
if (!$thumb_width) { $thumb_width = $config->get('theme_default_image_thumb_width'); }
if (!$thumb_height) { $thumb_height = $config->get('theme_default_image_thumb_height'); }
if (!$additional_width) { $additional_width = $config->get('config_image_additional_width'); }
if (!$additional_height) { $additional_height = $config->get('config_image_additional_height'); }
if (!$thumb_width) { $thumb_width = $config->get('config_image_thumb_width'); }
if (!$thumb_height) { $thumb_height = $config->get('config_image_thumb_height'); }
if (!$additional_width) { $additional_width = 74; }
if (!$additional_height) { $additional_height = 74; }
if (!$thumb_width) { $thumb_width = 228; }
if (!$thumb_height) { $thumb_height = 228; }
if ($support_svg && $support_svg_autofix) {
$svg_style = '<style>' . "\n" .
'.product-thumb .image img[src*=".svg"], .product-thumb .image img[src*=".SVG"], ' . "\n" .
'.thumbnail img[src*=".svg"], .thumbnail img[src*=".SVG"], ' . "\n" .
'.image-additional img[src*=".svg"], .image-additional img[src*=".SVG"], ' . "\n" .
'img[src*="/image/catalog/"][src*=".svg"], img[src*="/image/catalog/"][src*=".SVG"] {' . "\n" .
' max-width: 100% !important;' . "\n" .
' max-height: 100% !important;' . "\n" .
' object-fit: contain !important;' . "\n" .
'}' . "\n" .
'img.mfp-img[src*=".svg"], img.mfp-img[src*=".SVG"], #cboxLoadedContent img[src*=".svg"] {' . "\n" .
' width: 800px !important;' . "\n" .
' max-width: 100% !important;' . "\n" .
' height: auto !important;' . "\n" .
'}' . "\n" .
'.thumbnails img[src*=".svg"], .thumbnails img[src*=".SVG"] {' . "\n" .
' max-width: 100% !important;' . "\n" .
' max-height: 100% !important;' . "\n" .
' width: ' . $thumb_width . 'px !important;' . "\n" .
' height: ' . $thumb_height . 'px !important;' . "\n" .
' object-fit: contain !important;' . "\n" .
'}' . "\n" .
'</style>';
$output = str_ireplace('</head>', $svg_style . '</head>', $output);
}
if ($webp_on_fly || $lazy_load || $broken_fallback) {
$registry->get('load')->model('tool/image');
$model_tool_image = $registry->get('model_tool_image');
if ($webp_on_fly) {
$output = preg_replace_callback('/<a\b([^>]*)>/is', function($matches) use ($config, $registry, $model_tool_image, $webp_on_fly) {
$attrs_str = $matches[1];
preg_match_all('/(\b[\w\-:]+)\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|([^\s>]+))/is', $attrs_str, $attr_matches, PREG_SET_ORDER);
$attrs = array();
foreach ($attr_matches as $am) {
$name = strtolower($am[1]);
$val = ($am[2] !== '') ? $am[2] : (($am[3] !== '') ? $am[3] : $am[4]);
$attrs[$name] = $val;
}
if (!empty($attrs['href'])) {
$href = $attrs['href'];
$rel_path = '';
if (preg_match('/\\/image\\/(.*\\.(?:jpg|jpeg|png))/is', $href, $m_rel)) {
$rel_path = urldecode($m_rel[1]);
} elseif (preg_match('/^image\\/(.*\\.(?:jpg|jpeg|png))/is', $href, $m_rel)) {
$rel_path = urldecode($m_rel[1]);
}
$clean_rel_path = preg_replace('/\\?.*/', '', $rel_path);
$browser_supports_webp = isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false);
if ($browser_supports_webp && $clean_rel_path) {
$ext = strtolower(substr(strrchr($clean_rel_path, '.'), 1));
$phys_source = DIR_IMAGE . $clean_rel_path;
$phys_webp = DIR_IMAGE . preg_replace('/\\.(jpg|jpeg|png)$/i', '.webp', $clean_rel_path);
if (file_exists($phys_source)) {
if (!file_exists($phys_webp)) {
$img_data = @file_get_contents($phys_source);
if ($img_data) {
$im = @imagecreatefromstring($img_data);
if ($im) {
$webp_quality = (int)$config->get('module_img_opti_webp_quality');
if ($webp_quality <= 0 || $webp_quality > 100) {
$webp_quality = 80;
}
@imagewebp($im, $phys_webp, $webp_quality);
@imagedestroy($im);
}
}
}
if (file_exists($phys_webp)) {
$attrs['href'] = preg_replace('/\\.(jpg|jpeg|png)(\\?|$)/i', '.webp$2', $attrs['href']);
}
}
}
}
$new_attrs = array();
foreach ($attrs as $k => $v) {
$new_attrs[] = $k . '="' . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . '"';
}
return '<a ' . implode(' ', $new_attrs) . '>';
}, $output);
}
$output = preg_replace_callback('/<img\b([^>]*)>/is', function($matches) use ($config, $registry, $model_tool_image, $webp_on_fly, $lazy_load, $broken_fallback, $fallback_image) {
$attrs_str = $matches[1];
if (stripos($attrs_str, 'catalog_trash') !== false) {
return $matches[0];
}
preg_match_all('/(\b[\w\-:]+)\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|([^\s>]+))/is', $attrs_str, $attr_matches, PREG_SET_ORDER);
$attrs = array();
foreach ($attr_matches as $am) {
$name = strtolower($am[1]);
$val = ($am[2] !== '') ? $am[2] : (($am[3] !== '') ? $am[3] : $am[4]);
$attrs[$name] = $val;
}
$src = isset($attrs['src']) ? $attrs['src'] : '';
$data_src = isset($attrs['data-src']) ? $attrs['data-src'] : '';
$has_datasrc = ($data_src !== '');
$target_url = $has_datasrc ? $data_src : $src;
$rel_path = '';
if (preg_match('/\\/image\\/(.*\\.(?:jpg|jpeg|png|webp|svg))/is', $target_url, $m_rel)) {
$rel_path = urldecode($m_rel[1]);
} elseif (preg_match('/^image\\/(.*\\.(?:jpg|jpeg|png|webp|svg))/is', $target_url, $m_rel)) {
$rel_path = urldecode($m_rel[1]);
}
$clean_rel_path = preg_replace('/\\?.*/', '', $rel_path);
$browser_supports_webp = isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false);
if ($webp_on_fly && $browser_supports_webp && $clean_rel_path) {
$ext = strtolower(substr(strrchr($clean_rel_path, '.'), 1));
if (in_array($ext, array('jpg', 'jpeg', 'png'))) {
$phys_source = DIR_IMAGE . $clean_rel_path;
$phys_webp = DIR_IMAGE . preg_replace('/\\.(jpg|jpeg|png)$/i', '.webp', $clean_rel_path);
if (file_exists($phys_source)) {
if (!file_exists($phys_webp)) {
$img_data = @file_get_contents($phys_source);
if ($img_data) {
$im = @imagecreatefromstring($img_data);
if ($im) {
$webp_quality = (int)$config->get('module_img_opti_webp_quality');
if ($webp_quality <= 0 || $webp_quality > 100) {
$webp_quality = 80;
}
@imagewebp($im, $phys_webp, $webp_quality);
@imagedestroy($im);
}
}
}
if (file_exists($phys_webp)) {
if (isset($attrs['src'])) {
$attrs['src'] = preg_replace('/\\.(jpg|jpeg|png)(\\?|$)/i', '.webp$2', $attrs['src']);
}
if (isset($attrs['data-src'])) {
$attrs['data-src'] = preg_replace('/\\.(jpg|jpeg|png)(\\?|$)/i', '.webp$2', $attrs['data-src']);
}
}
}
}
}
if ($webp_on_fly && $browser_supports_webp) {
foreach (array('srcset', 'data-srcset') as $srcset_attr) {
if (isset($attrs[$srcset_attr])) {
$parts = explode(',', $attrs[$srcset_attr]);
foreach ($parts as &$part) {
$part = trim($part);
$subparts = preg_split('/\\s+/', $part);
if (!empty($subparts[0])) {
$s_url = $subparts[0];
$s_rel = '';
if (preg_match('/\\/image\\/(.*\\.(?:jpg|jpeg|png|webp|svg))/is', $s_url, $sm_rel)) {
$s_rel = urldecode($sm_rel[1]);
} elseif (preg_match('/^image\\/(.*\\.(?:jpg|jpeg|png|webp|svg))/is', $s_url, $sm_rel)) {
$s_rel = urldecode($sm_rel[1]);
}
$s_clean = preg_replace('/\\?.*/', '', $s_rel);
if ($s_clean) {
$s_ext = strtolower(substr(strrchr($s_clean, '.'), 1));
if (in_array($s_ext, array('jpg', 'jpeg', 'png'))) {
$s_phys_source = DIR_IMAGE . $s_clean;
$s_phys_webp = DIR_IMAGE . preg_replace('/\\.(jpg|jpeg|png)$/i', '.webp', $s_clean);
if (file_exists($s_phys_source)) {
if (!file_exists($s_phys_webp)) {
$img_data = @file_get_contents($s_phys_source);
if ($img_data) {
$im = @imagecreatefromstring($img_data);
if ($im) {
$webp_quality = (int)$config->get('module_img_opti_webp_quality');
if ($webp_quality <= 0 || $webp_quality > 100) {
$webp_quality = 80;
}
@imagewebp($im, $s_phys_webp, $webp_quality);
@imagedestroy($im);
}
}
}
if (file_exists($s_phys_webp)) {
$subparts[0] = preg_replace('/\\.(jpg|jpeg|png)(\\?|$)/i', '.webp$2', $s_url);
}
}
}
}
}
$part = implode(' ', $subparts);
}
$attrs[$srcset_attr] = implode(', ', $parts);
}
}
}
$is_svg = (strtolower(substr(strrchr($clean_rel_path, '.'), 1)) === 'svg');
if ($lazy_load && $clean_rel_path && is_file(DIR_IMAGE . $clean_rel_path) && !$is_svg) {
try {
$tiny_thumb = $model_tool_image->resize($clean_rel_path, 20, 20);
if ($has_datasrc) {
$attrs['src'] = $tiny_thumb;
} else {
$attrs['data-src'] = isset($attrs['src']) ? $attrs['src'] : '';
$attrs['src'] = $tiny_thumb;
}
if (isset($attrs['srcset'])) {
$attrs['data-srcset'] = $attrs['srcset'];
unset($attrs['srcset']);
}
$class = isset($attrs['class']) ? $attrs['class'] . ' img-lazyload' : 'img-lazyload';
$attrs['class'] = $class;
$style = 'filter: blur(10px); transition: filter 0.3s;';
if (isset($attrs['style'])) {
$attrs['style'] = rtrim(trim($attrs['style']), ';') . '; ' . $style;
} else {
$attrs['style'] = $style;
}
} catch (Exception $e) {}
}
if ($broken_fallback) {
$fallback_url = '';
$req_obj = $registry->get('request');
$is_https = isset($req_obj->server['HTTPS']) && ($req_obj->server['HTTPS'] == 'on' || $req_obj->server['HTTPS'] == '1');
$server_url = $is_https ? $config->get('config_ssl') : $config->get('config_url');
if ($fallback_image && is_file(DIR_IMAGE . $fallback_image)) {
$fallback_url = $server_url . 'image/' . $fallback_image;
} elseif ($config->get('config_logo') && is_file(DIR_IMAGE . $config->get('config_logo'))) {
$fallback_url = $server_url . 'image/' . $config->get('config_logo');
} else {
$fallback_url = $server_url . 'image/no_image.png';
}
if ($fallback_url) {
$attrs['onerror'] = "this.src='" . $fallback_url . "'; this.srcset=''; this.onerror=null;";
}
}
$new_attrs = array();
foreach ($attrs as $k => $v) {
$new_attrs[] = $k . '="' . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . '"';
}
return '<img ' . implode(' ', $new_attrs) . '>';
}, $output);
if ($lazy_load) {
$lazy_script = '<style>img.img-lazyload-loaded { filter: blur(0) !important; }</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.img-lazyload"));
if ("IntersectionObserver" in window) {
var lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var lazyImage = entry.target;
if (lazyImage.dataset.src) {
lazyImage.src = lazyImage.dataset.src;
}
if (lazyImage.dataset.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
lazyImage.addEventListener("load", function() {
lazyImage.classList.remove("img-lazyload");
lazyImage.classList.add("img-lazyload-loaded");
});
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
lazyImages.forEach(function(lazyImage) {
if (lazyImage.dataset.src) {
lazyImage.src = lazyImage.dataset.src;
}
if (lazyImage.dataset.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
lazyImage.style.filter = "none";
});
}
});
</script>
</body>';
$output = str_ireplace('</body>', $lazy_script, $output);
}
}
}
}
]]></add>
</operation>
</file>
<file path="catalog/controller/product/product.php">
<operation error="skip">
<search><![CDATA[if ($product_info['image']) {
$data['popup'] = $this->model_tool_image->resize($product_info['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_height'));
} else {
$data['popup'] = '';
}]]></search>
<add position="replace"><![CDATA[
if ($product_info['image'] || ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_broken_fallback') && $this->config->get('module_img_opti_fallback_image'))) {
$data['popup'] = $this->model_tool_image->resize($product_info['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_height'));
} else {
$data['popup'] = '';
}
]]></add>
</operation>
<operation error="skip">
<search><![CDATA[if ($product_info['image']) {
$data['thumb'] = $this->model_tool_image->resize($product_info['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_thumb_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_thumb_height'));
} else {
$data['thumb'] = '';
}]]></search>
<add position="replace"><![CDATA[
if ($product_info['image'] || ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_broken_fallback') && $this->config->get('module_img_opti_fallback_image'))) {
$data['thumb'] = $this->model_tool_image->resize($product_info['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_thumb_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_thumb_height'));
} else {
$data['thumb'] = '';
}
]]></add>
</operation>
</file>
<file path="system/framework.php">
<operation error="skip">
<search><![CDATA[$registry = new Registry();]]></search>
<add position="after"><![CDATA[
$GLOBALS['registry'] = $registry;
]]></add>
</operation>
</file>
<file path="system/library/sitecreator/trueFileManager/ControllerCommonTrueFileManager.php">
<operation error="skip">
<search><![CDATA['uploadAllow' => array('image/jpeg', 'image/png','image/webp', 'image/gif', 'image/svg+xml',]]></search>
<add position="replace" offset="2"><![CDATA['uploadAllow' => ($this->config->get('module_img_opti_status') && $this->config->get('module_img_opti_support_webp')) ? array('image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/svg+xml', 'image/pjpeg', 'image/x-png') : array('image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/pjpeg', 'image/x-png'),]]></add>
</operation>
</file>
<file path="system/library/sitecreator/elFinder/php/elFinderVolumeDriver.class.php">
<operation error="skip">
<search><![CDATA['image/vnd.adobe.photoshop' => 'psd']]></search>
<add position="after"><![CDATA[,
'image/webp' => 'webp',
'image/vnd.webp' => 'webp',
'image/x-webp' => 'webp']]></add>
</operation>
</file>
</modification>