Initial commit - prestashop-icons package
Semantic icon helper for PrestaShop modules. - Maps icon names to Font Awesome or Material Icons - Auto-detects admin context (Material) vs front (FA default) - Reads icon preference from ps_mpr_config table - Theme detection for Material Icons - PHP class + JavaScript helper Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
117
README.md
Normal file
117
README.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# PrestaShop Icons
|
||||
|
||||
Semantic icon helper for PrestaShop modules.
|
||||
|
||||
```php
|
||||
MprIcons::get('account'); // Just works
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
- **Admin**: Uses Material Icons (auto-detected)
|
||||
- **Front**: Reads from `ps_mpr_config` table, defaults to Font Awesome
|
||||
|
||||
## Setup (Module Install)
|
||||
|
||||
Call `init()` from your module's install method:
|
||||
|
||||
```php
|
||||
public function install()
|
||||
{
|
||||
MprIcons::init(); // Creates config table, detects theme icons
|
||||
return parent::install();
|
||||
}
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Create `ps_mpr_config` table if it doesn't exist
|
||||
2. Detect theme icon set (checks theme.yml, assets for Material)
|
||||
3. Save the detected preference
|
||||
|
||||
## PHP
|
||||
|
||||
```php
|
||||
use MyPrestaRocks\Icons\MprIcons;
|
||||
|
||||
// Just call get() - it figures out the rest
|
||||
echo MprIcons::get('account');
|
||||
echo MprIcons::get('cart');
|
||||
echo MprIcons::get('success', 'text-green'); // With extra class
|
||||
|
||||
// Get raw class/name (no HTML)
|
||||
$class = MprIcons::raw('edit'); // 'fa fa-pencil' or 'edit'
|
||||
```
|
||||
|
||||
## JavaScript
|
||||
|
||||
Include the script and set icon set from PHP:
|
||||
|
||||
```php
|
||||
// In your module
|
||||
$this->context->controller->addJS($this->getLocalPath() . 'vendor/myprestarocks/prestashop-icons/js/mpr-icons.js');
|
||||
Media::addJsDef(['mprIconSet' => MprIcons::getIconSet()]);
|
||||
```
|
||||
|
||||
```javascript
|
||||
MprIcons.get('account'); // HTML string
|
||||
MprIcons.create('warning'); // DOM element
|
||||
MprIcons.raw('edit'); // Class/name only
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Front office icon set is stored in `ps_mpr_config`:
|
||||
- module: `mpr_global`
|
||||
- key: `front_icon_set`
|
||||
- value: `fontawesome` or `material`
|
||||
|
||||
```php
|
||||
// Save preference
|
||||
MprIcons::saveIconSet('material');
|
||||
```
|
||||
|
||||
## Available Icons
|
||||
|
||||
| Name | Font Awesome | Material |
|
||||
|------|--------------|----------|
|
||||
| `account` | `fa fa-user` | `person` |
|
||||
| `cart` | `fa fa-shopping-cart` | `shopping_cart` |
|
||||
| `orders` | `fa fa-list` | `receipt_long` |
|
||||
| `success` | `fa fa-check` | `check` |
|
||||
| `error` | `fa fa-times` | `close` |
|
||||
| `warning` | `fa fa-exclamation-triangle` | `warning` |
|
||||
| `info` | `fa fa-info-circle` | `info` |
|
||||
| `edit` | `fa fa-pencil` | `edit` |
|
||||
| `delete` | `fa fa-trash` | `delete` |
|
||||
| `search` | `fa fa-search` | `search` |
|
||||
| `settings` | `fa fa-cog` | `settings` |
|
||||
| `email` | `fa fa-envelope` | `email` |
|
||||
| `phone` | `fa fa-phone` | `phone` |
|
||||
| `lock` | `fa fa-lock` | `lock` |
|
||||
| `logout` | `fa fa-sign-out` | `logout` |
|
||||
| `home` | `fa fa-home` | `home` |
|
||||
| `address` | `fa fa-map-marker` | `location_on` |
|
||||
| `truck` | `fa fa-truck` | `local_shipping` |
|
||||
| `credit-card` | `fa fa-credit-card` | `credit_card` |
|
||||
| `calendar` | `fa fa-calendar` | `calendar_today` |
|
||||
| `heart` | `fa fa-heart` | `favorite` |
|
||||
| `star` | `fa fa-star` | `star` |
|
||||
| `eye` | `fa fa-eye` | `visibility` |
|
||||
| `eye-off` | `fa fa-eye-slash` | `visibility_off` |
|
||||
| `close` | `fa fa-times` | `close` |
|
||||
| `check` | `fa fa-check` | `check` |
|
||||
| `plus` | `fa fa-plus` | `add` |
|
||||
| `minus` | `fa fa-minus` | `remove` |
|
||||
| `chevron-*` | `fa fa-chevron-*` | `chevron_*` |
|
||||
| `arrow-*` | `fa fa-arrow-*` | `arrow_*` |
|
||||
| `download` | `fa fa-download` | `download` |
|
||||
| `upload` | `fa fa-upload` | `upload` |
|
||||
| `refresh` | `fa fa-refresh` | `refresh` |
|
||||
| `spinner` | `fa fa-spinner fa-spin` | `hourglass_empty` |
|
||||
| `loading` | `fa fa-circle-o-notch fa-spin` | `autorenew` |
|
||||
|
||||
Full list: `MprIcons::list()`
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
14
composer.json
Normal file
14
composer.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "myprestarocks/prestashop-icons",
|
||||
"description": "Semantic icon helper for PrestaShop modules - maps icon names to Font Awesome or Material Icons",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyPrestaRocks\\Icons\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
}
|
||||
}
|
||||
153
js/mpr-icons.js
Normal file
153
js/mpr-icons.js
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* MprIcons - Semantic Icon Helper for PrestaShop (JavaScript)
|
||||
*
|
||||
* Simple API: MprIcons.get('account') - that's it.
|
||||
*
|
||||
* Set window.mprIconSet from PHP to configure (defaults to 'fontawesome').
|
||||
*
|
||||
* @package myprestarocks/prestashop-icons
|
||||
*/
|
||||
|
||||
var MprIcons = (function() {
|
||||
'use strict';
|
||||
|
||||
var FA = 'fontawesome';
|
||||
var MATERIAL = 'material';
|
||||
|
||||
var map = {
|
||||
// User
|
||||
'account': ['fa fa-user', 'person'],
|
||||
'user': ['fa fa-user', 'person'],
|
||||
'logout': ['fa fa-sign-out', 'logout'],
|
||||
'login': ['fa fa-sign-in', 'login'],
|
||||
|
||||
// E-commerce
|
||||
'cart': ['fa fa-shopping-cart', 'shopping_cart'],
|
||||
'orders': ['fa fa-list', 'receipt_long'],
|
||||
'truck': ['fa fa-truck', 'local_shipping'],
|
||||
'credit-card': ['fa fa-credit-card', 'credit_card'],
|
||||
'gift': ['fa fa-gift', 'card_giftcard'],
|
||||
'tag': ['fa fa-tag', 'local_offer'],
|
||||
'percent': ['fa fa-percent', 'percent'],
|
||||
|
||||
// Status
|
||||
'success': ['fa fa-check', 'check'],
|
||||
'error': ['fa fa-times', 'close'],
|
||||
'warning': ['fa fa-exclamation-triangle', 'warning'],
|
||||
'info': ['fa fa-info-circle', 'info'],
|
||||
|
||||
// Actions
|
||||
'edit': ['fa fa-pencil', 'edit'],
|
||||
'delete': ['fa fa-trash', 'delete'],
|
||||
'search': ['fa fa-search', 'search'],
|
||||
'settings': ['fa fa-cog', 'settings'],
|
||||
'download': ['fa fa-download', 'download'],
|
||||
'upload': ['fa fa-upload', 'upload'],
|
||||
'refresh': ['fa fa-refresh', 'refresh'],
|
||||
'save': ['fa fa-save', 'save'],
|
||||
'print': ['fa fa-print', 'print'],
|
||||
'copy': ['fa fa-copy', 'content_copy'],
|
||||
|
||||
// UI
|
||||
'close': ['fa fa-times', 'close'],
|
||||
'check': ['fa fa-check', 'check'],
|
||||
'plus': ['fa fa-plus', 'add'],
|
||||
'minus': ['fa fa-minus', 'remove'],
|
||||
'menu': ['fa fa-bars', 'menu'],
|
||||
'more': ['fa fa-ellipsis-v', 'more_vert'],
|
||||
|
||||
// Arrows
|
||||
'arrow-left': ['fa fa-arrow-left', 'arrow_back'],
|
||||
'arrow-right': ['fa fa-arrow-right', 'arrow_forward'],
|
||||
'arrow-up': ['fa fa-arrow-up', 'arrow_upward'],
|
||||
'arrow-down': ['fa fa-arrow-down', 'arrow_downward'],
|
||||
'chevron-left': ['fa fa-chevron-left', 'chevron_left'],
|
||||
'chevron-right': ['fa fa-chevron-right', 'chevron_right'],
|
||||
'chevron-up': ['fa fa-chevron-up', 'expand_less'],
|
||||
'chevron-down': ['fa fa-chevron-down', 'expand_more'],
|
||||
|
||||
// Communication
|
||||
'email': ['fa fa-envelope', 'email'],
|
||||
'phone': ['fa fa-phone', 'phone'],
|
||||
'comment': ['fa fa-comment', 'comment'],
|
||||
'chat': ['fa fa-comments', 'chat'],
|
||||
|
||||
// Security
|
||||
'lock': ['fa fa-lock', 'lock'],
|
||||
'unlock': ['fa fa-unlock', 'lock_open'],
|
||||
'shield': ['fa fa-shield', 'shield'],
|
||||
'key': ['fa fa-key', 'vpn_key'],
|
||||
|
||||
// Misc
|
||||
'home': ['fa fa-home', 'home'],
|
||||
'address': ['fa fa-map-marker', 'location_on'],
|
||||
'calendar': ['fa fa-calendar', 'calendar_today'],
|
||||
'clock': ['fa fa-clock-o', 'schedule'],
|
||||
'heart': ['fa fa-heart', 'favorite'],
|
||||
'star': ['fa fa-star', 'star'],
|
||||
'eye': ['fa fa-eye', 'visibility'],
|
||||
'eye-off': ['fa fa-eye-slash', 'visibility_off'],
|
||||
'file': ['fa fa-file', 'description'],
|
||||
'folder': ['fa fa-folder', 'folder'],
|
||||
'image': ['fa fa-image', 'image'],
|
||||
'link': ['fa fa-link', 'link'],
|
||||
'external': ['fa fa-external-link', 'open_in_new'],
|
||||
'help': ['fa fa-question-circle', 'help'],
|
||||
|
||||
// Loading
|
||||
'spinner': ['fa fa-spinner fa-spin', 'hourglass_empty'],
|
||||
'loading': ['fa fa-circle-o-notch fa-spin', 'autorenew']
|
||||
};
|
||||
|
||||
function getIconSet() {
|
||||
return window.mprIconSet || FA;
|
||||
}
|
||||
|
||||
function get(name, extraClass) {
|
||||
if (!map[name]) return '';
|
||||
|
||||
var set = getIconSet();
|
||||
var extra = extraClass ? ' ' + extraClass : '';
|
||||
|
||||
if (set === MATERIAL) {
|
||||
return '<i class="material-icons' + extra + '">' + map[name][1] + '</i>';
|
||||
}
|
||||
return '<i class="' + map[name][0] + extra + '"></i>';
|
||||
}
|
||||
|
||||
function raw(name) {
|
||||
if (!map[name]) return '';
|
||||
var set = getIconSet();
|
||||
return set === MATERIAL ? map[name][1] : map[name][0];
|
||||
}
|
||||
|
||||
function create(name, extraClass) {
|
||||
var html = get(name, extraClass);
|
||||
if (!html) return null;
|
||||
var temp = document.createElement('div');
|
||||
temp.innerHTML = html;
|
||||
return temp.firstChild;
|
||||
}
|
||||
|
||||
function exists(name) {
|
||||
return !!map[name];
|
||||
}
|
||||
|
||||
function list() {
|
||||
return Object.keys(map);
|
||||
}
|
||||
|
||||
return {
|
||||
get: get,
|
||||
raw: raw,
|
||||
create: create,
|
||||
exists: exists,
|
||||
list: list,
|
||||
FA: FA,
|
||||
MATERIAL: MATERIAL
|
||||
};
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = MprIcons;
|
||||
}
|
||||
370
src/MprIcons.php
Normal file
370
src/MprIcons.php
Normal file
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MprIcons - Semantic Icon Helper for PrestaShop
|
||||
*
|
||||
* Simple API: MprIcons::get('account') - that's it.
|
||||
*
|
||||
* - Admin: auto-detects and uses Material Icons
|
||||
* - Front: reads icon set from ps_mpr_config table
|
||||
*
|
||||
* @package myprestarocks/prestashop-icons
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Icons;
|
||||
|
||||
class MprIcons
|
||||
{
|
||||
const FA = 'fontawesome';
|
||||
const MATERIAL = 'material';
|
||||
|
||||
const CONFIG_TABLE = 'mpr_config';
|
||||
const CONFIG_MODULE = 'mpr_global';
|
||||
const CONFIG_KEY = 'front_icon_set';
|
||||
|
||||
private static $iconSet = null;
|
||||
|
||||
/**
|
||||
* Semantic name => [FA class, Material name]
|
||||
*/
|
||||
private static $map = [
|
||||
// User
|
||||
'account' => ['fa fa-user', 'person'],
|
||||
'user' => ['fa fa-user', 'person'],
|
||||
'logout' => ['fa fa-sign-out', 'logout'],
|
||||
'login' => ['fa fa-sign-in', 'login'],
|
||||
|
||||
// E-commerce
|
||||
'cart' => ['fa fa-shopping-cart', 'shopping_cart'],
|
||||
'orders' => ['fa fa-list', 'receipt_long'],
|
||||
'truck' => ['fa fa-truck', 'local_shipping'],
|
||||
'credit-card' => ['fa fa-credit-card', 'credit_card'],
|
||||
'gift' => ['fa fa-gift', 'card_giftcard'],
|
||||
'tag' => ['fa fa-tag', 'local_offer'],
|
||||
'percent' => ['fa fa-percent', 'percent'],
|
||||
|
||||
// Status
|
||||
'success' => ['fa fa-check', 'check'],
|
||||
'error' => ['fa fa-times', 'close'],
|
||||
'warning' => ['fa fa-exclamation-triangle', 'warning'],
|
||||
'info' => ['fa fa-info-circle', 'info'],
|
||||
|
||||
// Actions
|
||||
'edit' => ['fa fa-pencil', 'edit'],
|
||||
'delete' => ['fa fa-trash', 'delete'],
|
||||
'search' => ['fa fa-search', 'search'],
|
||||
'settings' => ['fa fa-cog', 'settings'],
|
||||
'download' => ['fa fa-download', 'download'],
|
||||
'upload' => ['fa fa-upload', 'upload'],
|
||||
'refresh' => ['fa fa-refresh', 'refresh'],
|
||||
'save' => ['fa fa-save', 'save'],
|
||||
'print' => ['fa fa-print', 'print'],
|
||||
'copy' => ['fa fa-copy', 'content_copy'],
|
||||
|
||||
// UI
|
||||
'close' => ['fa fa-times', 'close'],
|
||||
'check' => ['fa fa-check', 'check'],
|
||||
'plus' => ['fa fa-plus', 'add'],
|
||||
'minus' => ['fa fa-minus', 'remove'],
|
||||
'menu' => ['fa fa-bars', 'menu'],
|
||||
'more' => ['fa fa-ellipsis-v', 'more_vert'],
|
||||
|
||||
// Arrows
|
||||
'arrow-left' => ['fa fa-arrow-left', 'arrow_back'],
|
||||
'arrow-right' => ['fa fa-arrow-right', 'arrow_forward'],
|
||||
'arrow-up' => ['fa fa-arrow-up', 'arrow_upward'],
|
||||
'arrow-down' => ['fa fa-arrow-down', 'arrow_downward'],
|
||||
'chevron-left' => ['fa fa-chevron-left', 'chevron_left'],
|
||||
'chevron-right' => ['fa fa-chevron-right', 'chevron_right'],
|
||||
'chevron-up' => ['fa fa-chevron-up', 'expand_less'],
|
||||
'chevron-down' => ['fa fa-chevron-down', 'expand_more'],
|
||||
|
||||
// Communication
|
||||
'email' => ['fa fa-envelope', 'email'],
|
||||
'phone' => ['fa fa-phone', 'phone'],
|
||||
'comment' => ['fa fa-comment', 'comment'],
|
||||
'chat' => ['fa fa-comments', 'chat'],
|
||||
|
||||
// Security
|
||||
'lock' => ['fa fa-lock', 'lock'],
|
||||
'unlock' => ['fa fa-unlock', 'lock_open'],
|
||||
'shield' => ['fa fa-shield', 'shield'],
|
||||
'key' => ['fa fa-key', 'vpn_key'],
|
||||
|
||||
// Misc
|
||||
'home' => ['fa fa-home', 'home'],
|
||||
'address' => ['fa fa-map-marker', 'location_on'],
|
||||
'calendar' => ['fa fa-calendar', 'calendar_today'],
|
||||
'clock' => ['fa fa-clock-o', 'schedule'],
|
||||
'heart' => ['fa fa-heart', 'favorite'],
|
||||
'star' => ['fa fa-star', 'star'],
|
||||
'eye' => ['fa fa-eye', 'visibility'],
|
||||
'eye-off' => ['fa fa-eye-slash', 'visibility_off'],
|
||||
'file' => ['fa fa-file', 'description'],
|
||||
'folder' => ['fa fa-folder', 'folder'],
|
||||
'image' => ['fa fa-image', 'image'],
|
||||
'link' => ['fa fa-link', 'link'],
|
||||
'external' => ['fa fa-external-link', 'open_in_new'],
|
||||
'help' => ['fa fa-question-circle', 'help'],
|
||||
|
||||
// Loading
|
||||
'spinner' => ['fa fa-spinner fa-spin', 'hourglass_empty'],
|
||||
'loading' => ['fa fa-circle-o-notch fa-spin', 'autorenew'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get icon HTML - main method
|
||||
*
|
||||
* @param string $name Semantic icon name
|
||||
* @param string $class Extra CSS classes (optional)
|
||||
* @return string HTML
|
||||
*/
|
||||
public static function get(string $name, string $class = ''): string
|
||||
{
|
||||
if (!isset(self::$map[$name])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$set = self::getIconSet();
|
||||
[$fa, $material] = self::$map[$name];
|
||||
$extra = $class ? ' ' . $class : '';
|
||||
|
||||
if ($set === self::MATERIAL) {
|
||||
return '<i class="material-icons' . $extra . '">' . $material . '</i>';
|
||||
}
|
||||
|
||||
return '<i class="' . $fa . $extra . '"></i>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get raw class/name without HTML wrapper
|
||||
*/
|
||||
public static function raw(string $name): string
|
||||
{
|
||||
if (!isset(self::$map[$name])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$set = self::getIconSet();
|
||||
[$fa, $material] = self::$map[$name];
|
||||
|
||||
return $set === self::MATERIAL ? $material : $fa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect and cache the icon set to use
|
||||
*/
|
||||
public static function getIconSet(): string
|
||||
{
|
||||
if (self::$iconSet !== null) {
|
||||
return self::$iconSet;
|
||||
}
|
||||
|
||||
// Admin context = Material Icons
|
||||
if (defined('_PS_ADMIN_DIR_')) {
|
||||
self::$iconSet = self::MATERIAL;
|
||||
return self::$iconSet;
|
||||
}
|
||||
|
||||
// Front office - read from config table
|
||||
self::$iconSet = self::readConfigTable() ?: self::FA;
|
||||
return self::$iconSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read icon set preference from ps_mpr_config table
|
||||
*/
|
||||
private static function readConfigTable(): ?string
|
||||
{
|
||||
if (!defined('_DB_PREFIX_')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$table = _DB_PREFIX_ . self::CONFIG_TABLE;
|
||||
$sql = "SELECT `value` FROM `{$table}`
|
||||
WHERE `module` = '" . pSQL(self::CONFIG_MODULE) . "'
|
||||
AND `key` = '" . pSQL(self::CONFIG_KEY) . "'";
|
||||
|
||||
$result = \Db::getInstance()->getValue($sql);
|
||||
|
||||
if ($result && in_array($result, [self::FA, self::MATERIAL])) {
|
||||
return $result;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Table doesn't exist or query failed - use default
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save icon set preference to ps_mpr_config table
|
||||
*/
|
||||
public static function saveIconSet(string $set): bool
|
||||
{
|
||||
if (!in_array($set, [self::FA, self::MATERIAL])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!defined('_DB_PREFIX_')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$table = _DB_PREFIX_ . self::CONFIG_TABLE;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
$sql = "INSERT INTO `{$table}` (`module`, `key`, `value`, `date_add`, `date_upd`)
|
||||
VALUES ('" . pSQL(self::CONFIG_MODULE) . "', '" . pSQL(self::CONFIG_KEY) . "', '" . pSQL($set) . "', '{$now}', '{$now}')
|
||||
ON DUPLICATE KEY UPDATE `value` = '" . pSQL($set) . "', `date_upd` = '{$now}'";
|
||||
|
||||
$result = \Db::getInstance()->execute($sql);
|
||||
|
||||
if ($result) {
|
||||
self::$iconSet = null; // Clear cache
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a specific icon set (for testing or overriding)
|
||||
*/
|
||||
public static function setIconSet(string $set): void
|
||||
{
|
||||
if (in_array($set, [self::FA, self::MATERIAL])) {
|
||||
self::$iconSet = $set;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached icon set
|
||||
*/
|
||||
public static function clearCache(): void
|
||||
{
|
||||
self::$iconSet = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize icon system - call from module install
|
||||
* Creates config table if needed, sets default icon set
|
||||
*/
|
||||
public static function init(): bool
|
||||
{
|
||||
if (!self::ensureConfigTable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no config exists, detect and save default
|
||||
$current = self::readConfigTable();
|
||||
if ($current === null) {
|
||||
$detected = self::detectThemeIcons();
|
||||
self::saveIconSet($detected);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure ps_mpr_config table exists
|
||||
*/
|
||||
public static function ensureConfigTable(): bool
|
||||
{
|
||||
if (!defined('_DB_PREFIX_')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$table = _DB_PREFIX_ . self::CONFIG_TABLE;
|
||||
|
||||
// Check if table exists
|
||||
$exists = \Db::getInstance()->getValue(
|
||||
"SELECT COUNT(*) FROM information_schema.tables
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = '{$table}'"
|
||||
);
|
||||
|
||||
if ((int)$exists > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create table
|
||||
$sql = "CREATE TABLE IF NOT EXISTS `{$table}` (
|
||||
`id_config` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`module` VARCHAR(64) NOT NULL,
|
||||
`key` VARCHAR(128) NOT NULL,
|
||||
`value` TEXT DEFAULT NULL,
|
||||
`date_add` DATETIME NOT NULL,
|
||||
`date_upd` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id_config`),
|
||||
UNIQUE KEY `module_key` (`module`, `key`),
|
||||
KEY `module` (`module`)
|
||||
) ENGINE=" . _MYSQL_ENGINE_ . " DEFAULT CHARSET=utf8mb4;";
|
||||
|
||||
return \Db::getInstance()->execute($sql);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect which icon set the current theme likely uses
|
||||
* Returns 'fontawesome' for most PrestaShop themes
|
||||
*/
|
||||
public static function detectThemeIcons(): string
|
||||
{
|
||||
// Most PrestaShop themes (including classic) use Font Awesome
|
||||
// Only return Material if we can positively detect it
|
||||
|
||||
if (!defined('_PS_THEME_DIR_')) {
|
||||
return self::FA;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check theme.yml for icon hints
|
||||
$themeYml = _PS_THEME_DIR_ . 'config/theme.yml';
|
||||
if (file_exists($themeYml)) {
|
||||
$content = file_get_contents($themeYml);
|
||||
if (strpos($content, 'material') !== false || strpos($content, 'Material') !== false) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if theme has material-icons in assets
|
||||
$assetsDir = _PS_THEME_DIR_ . 'assets/css/';
|
||||
if (is_dir($assetsDir)) {
|
||||
$files = scandir($assetsDir);
|
||||
foreach ($files as $file) {
|
||||
if (strpos($file, 'material') !== false) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Ignore detection errors
|
||||
}
|
||||
|
||||
// Default to Font Awesome (safe for 95% of themes)
|
||||
return self::FA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if icon exists
|
||||
*/
|
||||
public static function exists(string $name): bool
|
||||
{
|
||||
return isset(self::$map[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available icon names
|
||||
*/
|
||||
public static function list(): array
|
||||
{
|
||||
return array_keys(self::$map);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user