From 28f8794e161e492b7d5afbc42258c5bd6c5d4757 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Thu, 20 Nov 2025 09:53:31 +0100 Subject: [PATCH 1/4] feat(extra-features): Add svg icon and price splitter smarty functions These are just helpers and useful for many prestashop designs --- .../src/Core/Smarty/SmartyHelperFunctions.php | 75 +++++++++++++++++++ is_themecore/src/Hook/Smarty.php | 10 +++ 2 files changed, 85 insertions(+) diff --git a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php index a28ea5f..36399ee 100644 --- a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php +++ b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php @@ -195,4 +195,79 @@ class SmartyHelperFunctions $calculator = new ColorBrightnessCalculator(); return $calculator->isBright($hexColor); } + + /* Helper to display SVG icons stored in themes/falcon/_dev/img/icons/ + + Registered under public_html/config/smartyfront.config.inc.php + + Usage examples in a TPL file: + + {svg_icon file='person.svg' color='red' width='24' height='24'} + {svg_icon file='person.svg' color='#3498db'} + {svg_icon file='person.svg' width='32'} + + */ + public static function displaySvgIcon($params) + { + if (empty($params['file'])) { + return ''; + } + + // The path to the icons directory + $icon_path = _PS_THEME_DIR_ . '/_dev/img/' . basename($params['file']); + + // If there aint an image, display a basic error message on dev mode + if (!is_file($icon_path)) { + if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) { + return 'Invalid SVG path: ' . htmlspecialchars($icon_path); + } + return ''; + } + + $svg_content = file_get_contents($icon_path); + + // Build style attribute from parameters + $styles = []; + if (!empty($params['width'])) { + $styles[] = 'width: ' . $params['width'] . (is_numeric($params['width']) ? 'px' : ''); + } + if (!empty($params['height'])) { + $styles[] = 'height: ' . $params['height'] . (is_numeric($params['height']) ? 'px' : ''); + } + if (!empty($params['color'])) { + $styles[] = 'color: ' . $params['color']; + } + + // If we have styles to apply, add them to the SVG + if (!empty($styles)) { + $style_attr = 'style="' . implode('; ', $styles) . '"'; + $svg_content = preg_replace('/(]*?)>/', '$1 ' . $style_attr . '>', $svg_content); + } + + return $svg_content; + } + /* Helper to split the price into euros and cents to make it more stylish + + Usage examples in a TPL file: + {price_split price=$product.price} + + */ + public static function displayPriceSplit($price) + { + //Convert to a string and only keep numbers, commas and dots + $price_string = implode(',', $price); + $price_string = preg_replace('/[^0-9,.]/', '', $price_string); + + // Split by comma and wrap each part in a span + $price_parts = explode(',', $price_string); + if (count($price_parts) >= 2) { + echo '' . $price_parts[0] . ''; + echo '' . $price_parts[1] . ''; + } else { + foreach ($price_parts as $part) { + echo '' . $part . ''; + } + } + } + } diff --git a/is_themecore/src/Hook/Smarty.php b/is_themecore/src/Hook/Smarty.php index 7a9fc00..a83f7ec 100644 --- a/is_themecore/src/Hook/Smarty.php +++ b/is_themecore/src/Hook/Smarty.php @@ -56,5 +56,15 @@ public function hookActionDispatcherBefore(): void } else { return; } + if (!isset($this->context->smarty->registered_plugins['function']['svg_icon'])) { + $this->context->smarty->registerPlugin('function', 'svg_icon', ['Oksydan\Module\IsThemeCore\Core\Smarty\SmartyHelperFunctions', 'displaySvgIcon']); + } else { + return; + } + if (!isset($this->context->smarty->registered_plugins['function']['price_split'])) { + $this->context->smarty->registerPlugin('function', 'price_split', ['Oksydan\Module\IsThemeCore\Core\Smarty\SmartyHelperFunctions', 'displayPriceSplit']); + } else { + return; + } } } From e2c4f265c2795fb4b607ad10da22a75ffc47ba4d Mon Sep 17 00:00:00 2001 From: Isabelle Date: Wed, 31 Dec 2025 13:56:41 +0100 Subject: [PATCH 2/4] feat(extra-features): Refactor smarty helper --- .../src/Core/Smarty/SmartyHelperFunctions.php | 89 ++++++++++++------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php index 36399ee..39220c2 100644 --- a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php +++ b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php @@ -190,25 +190,28 @@ class SmartyHelperFunctions return $content; } - public static function isBright($hexColor) + + +/* CUSTOM ADDITIONS BELOW */ + + + public static function isBright($hexColor) { $calculator = new ColorBrightnessCalculator(); return $calculator->isBright($hexColor); } - /* Helper to display SVG icons stored in themes/falcon/_dev/img/icons/ - - Registered under public_html/config/smartyfront.config.inc.php + public static function displaySvgIcon($params){ + /* + Helper to display SVG icons stored in themes/falcon/_dev/img/icons/ + registered under public_html/modules/is_themecore/src/Hook/Smarty.php Usage examples in a TPL file: - {svg_icon file='person.svg' color='red' width='24' height='24'} - {svg_icon file='person.svg' color='#3498db'} - {svg_icon file='person.svg' width='32'} - + {svg_icon file='person.svg' fill='red' width='24' height='24'} + {svg_icon file='person.svg'} */ - public static function displaySvgIcon($params) - { + if (empty($params['file'])) { return ''; } @@ -226,34 +229,53 @@ class SmartyHelperFunctions $svg_content = file_get_contents($icon_path); - // Build style attribute from parameters - $styles = []; - if (!empty($params['width'])) { - $styles[] = 'width: ' . $params['width'] . (is_numeric($params['width']) ? 'px' : ''); - } - if (!empty($params['height'])) { - $styles[] = 'height: ' . $params['height'] . (is_numeric($params['height']) ? 'px' : ''); - } - if (!empty($params['color'])) { - $styles[] = 'color: ' . $params['color']; - } - - // If we have styles to apply, add them to the SVG - if (!empty($styles)) { - $style_attr = 'style="' . implode('; ', $styles) . '"'; - $svg_content = preg_replace('/(]*?)>/', '$1 ' . $style_attr . '>', $svg_content); - } - + // Define SVG attributes that should be replaced/added + $svg_attributes = [ + 'width', + 'height', + 'fill', + 'stroke', + 'stroke-width', + 'opacity', + 'viewBox', + ]; + + foreach ($svg_attributes as $attr) { + if (!empty($params[$attr])) { + $value = $params[$attr]; + + // Check if attribute already exists in the SVG + if (preg_match('/' . preg_quote($attr) . '="[^"]*"/', $svg_content)) { + // Replace existing attribute + $svg_content = preg_replace( + '/' . preg_quote($attr) . '="[^"]*"/', + $attr . '="' . $value . '"', + $svg_content + ); + } else { + // Add new attribute to the opening tag + $svg_content = preg_replace( + '/(]*?)>/', + '$1 ' . $attr . '="' . $value . '">', + $svg_content, + 1 // Only replace the first occurrence + ); + } + } + } return $svg_content; } - /* Helper to split the price into euros and cents to make it more stylish + + + public static function displayPriceSplit($price){ + /* Helper to split the price into euros and cents to make it more stylish + registered under public_html/modules/is_themecore/src/Hook/Smarty.php Usage examples in a TPL file: {price_split price=$product.price} - */ - public static function displayPriceSplit($price) - { + */ + //Convert to a string and only keep numbers, commas and dots $price_string = implode(',', $price); $price_string = preg_replace('/[^0-9,.]/', '', $price_string); @@ -269,5 +291,4 @@ class SmartyHelperFunctions } } } - -} +} \ No newline at end of file From ea9b67ffc5a95894e57245e8c391700bdb166992 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Wed, 31 Dec 2025 15:16:21 +0100 Subject: [PATCH 3/4] fix(extra-features): Add attributes & styles to displaySvgIcon method --- .../src/Core/Smarty/SmartyHelperFunctions.php | 78 ++++++++++--------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php index 39220c2..88f40bf 100644 --- a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php +++ b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php @@ -192,6 +192,7 @@ class SmartyHelperFunctions } + /* CUSTOM ADDITIONS BELOW */ @@ -212,14 +213,12 @@ class SmartyHelperFunctions {svg_icon file='person.svg'} */ + // Grab svg under falcon/_dev/img and display an error if not found if (empty($params['file'])) { return ''; } - - // The path to the icons directory $icon_path = _PS_THEME_DIR_ . '/_dev/img/' . basename($params['file']); - // If there aint an image, display a basic error message on dev mode if (!is_file($icon_path)) { if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) { return 'Invalid SVG path: ' . htmlspecialchars($icon_path); @@ -229,40 +228,49 @@ class SmartyHelperFunctions $svg_content = file_get_contents($icon_path); - // Define SVG attributes that should be replaced/added - $svg_attributes = [ - 'width', - 'height', - 'fill', - 'stroke', - 'stroke-width', - 'opacity', - 'viewBox', - ]; - - foreach ($svg_attributes as $attr) { - if (!empty($params[$attr])) { - $value = $params[$attr]; - - // Check if attribute already exists in the SVG - if (preg_match('/' . preg_quote($attr) . '="[^"]*"/', $svg_content)) { - // Replace existing attribute - $svg_content = preg_replace( - '/' . preg_quote($attr) . '="[^"]*"/', - $attr . '="' . $value . '"', - $svg_content - ); - } else { - // Add new attribute to the opening tag - $svg_content = preg_replace( - '/(]*?)>/', - '$1 ' . $attr . '="' . $value . '">', - $svg_content, - 1 // Only replace the first occurrence - ); - } + /* Define an associative array of SVG properties + If the property is a style, addd it in a style tag. + If the property is an attribute, replace it in the svg code. + + This reduces the risk of interfering with other attributes. */ + $svg_props = array( + 'width' => 'style', + 'height' => 'style', + 'opacity' => 'style', + 'fill' => 'attribute', + 'stroke' => 'attribute', + ); + + // Styles + $styles = []; + foreach ($svg_props as $prop => $type) { + if ($type === 'style' && !empty($params[$prop])) { + $value = $params[$prop]; + if (in_array($prop, ['width', 'height']) && is_numeric($value)) { + $value .= 'px'; } + $styles[] = $prop . ': ' . $value; } + } + if (!empty($styles)) { + $style_attr = 'style="' . implode('; ', $styles) . '"'; + $svg_content = preg_replace('/(]*?)>/', '$1 ' . $style_attr . '>', $svg_content, 1); + } + + // Attributes + foreach ($svg_props as $prop => $type) { + if ($type === 'attribute' && !empty($params[$prop])) { + $value = $params[$prop]; + // Use word boundaries to avoid matching partial names like fill-opacity or stroke-width + // Replace ALL occurrences of the attribute + $svg_content = preg_replace( + '/\b' . preg_quote($prop) . '\b\s*=\s*"[^"]*"/', + $prop . '="' . $value . '"', + $svg_content + ); + } + } + return $svg_content; } From 92fd21d1370326bf36b891e11829bf92bd0f4396 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 17 Feb 2026 09:57:47 +0100 Subject: [PATCH 4/4] feat(extra-features): Update price_split to be more dynamic Added show_currency bool as a parameter; made the span class and aria-label displaying the currency dynamic for accessibility --- is_themecore/src/Core/Smarty/SmartyHelperFunctions.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php index 88f40bf..af12eb4 100644 --- a/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php +++ b/is_themecore/src/Core/Smarty/SmartyHelperFunctions.php @@ -275,7 +275,7 @@ class SmartyHelperFunctions } - public static function displayPriceSplit($price){ + public static function displayPriceSplit($price, $show_currency = false) { /* Helper to split the price into euros and cents to make it more stylish registered under public_html/modules/is_themecore/src/Hook/Smarty.php @@ -283,15 +283,16 @@ class SmartyHelperFunctions {price_split price=$product.price} */ - //Convert to a string and only keep numbers, commas and dots + $currency_name = \Context::getContext()->currency->name; + $currency_symbol = \Context::getContext()->currency->symbol; $price_string = implode(',', $price); $price_string = preg_replace('/[^0-9,.]/', '', $price_string); // Split by comma and wrap each part in a span $price_parts = explode(',', $price_string); if (count($price_parts) >= 2) { - echo '' . $price_parts[0] . ''; + echo '' . ($show_currency ? $currency_symbol : '') . $price_parts[0] . ''; echo '' . $price_parts[1] . ''; } else { foreach ($price_parts as $part) {