Fix icon detection: check theme.css content for Material Icons
PS 1.7+ classic theme bundles Material Icons inside theme.css via webpack — no separate material-icons.css file exists. The old detection only scanned filenames, so it wrongly defaulted to FA. Now reads the first 50KB of theme.css to check for 'Material Icons' or 'FontAwesome' font-face declarations. Falls back to version-based default: Material for PS 1.7+, FA for PS 1.6. Also fixes themeHasIconFont() to use the same CSS content check, so self-hosted icons are correctly skipped when the theme provides them. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
107
src/MprIcons.php
107
src/MprIcons.php
@@ -379,9 +379,12 @@ class MprIcons
|
||||
/**
|
||||
* Detect which icon set the current theme uses
|
||||
*
|
||||
* Checks theme config and assets for Material Icons indicators.
|
||||
* Returns 'fontawesome' for classic and most themes,
|
||||
* 'material' for Hummingbird and Material-based themes.
|
||||
* PS 1.6 themes use Font Awesome.
|
||||
* PS 1.7+ themes (classic, hummingbird, etc.) bundle Material Icons
|
||||
* inside theme.css — no separate CSS file to scan for.
|
||||
*
|
||||
* Strategy: read the first ~50KB of theme.css and check for
|
||||
* 'Material Icons' font-face. Fast, reliable, works across all versions.
|
||||
*/
|
||||
public static function detectThemeIcons(): string
|
||||
{
|
||||
@@ -390,19 +393,32 @@ class MprIcons
|
||||
}
|
||||
|
||||
try {
|
||||
// PS 1.7+ — check theme.yml
|
||||
$themeYml = _PS_THEME_DIR_ . 'config/theme.yml';
|
||||
if (file_exists($themeYml)) {
|
||||
$content = file_get_contents($themeYml);
|
||||
if (stripos($content, 'hummingbird') !== false) {
|
||||
return self::MATERIAL;
|
||||
// Check compiled theme CSS for Material Icons font-face
|
||||
// PS 1.7+ bundles icons into theme.css via webpack
|
||||
$cssFiles = [
|
||||
_PS_THEME_DIR_ . 'assets/css/theme.css',
|
||||
_PS_THEME_DIR_ . 'css/theme.css',
|
||||
];
|
||||
|
||||
foreach ($cssFiles as $cssFile) {
|
||||
if (!file_exists($cssFile)) {
|
||||
continue;
|
||||
}
|
||||
if (stripos($content, 'material-icons') !== false || stripos($content, 'material_icons') !== false) {
|
||||
return self::MATERIAL;
|
||||
// Read first 50KB — font-face is always near the top
|
||||
$handle = fopen($cssFile, 'r');
|
||||
if ($handle) {
|
||||
$chunk = fread($handle, 51200);
|
||||
fclose($handle);
|
||||
if (stripos($chunk, 'Material Icons') !== false) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
if (stripos($chunk, 'FontAwesome') !== false) {
|
||||
return self::FA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check theme assets for material-icons CSS
|
||||
// Fallback: check for separate icon CSS files
|
||||
$dirs = [
|
||||
_PS_THEME_DIR_ . 'assets/css/',
|
||||
_PS_THEME_DIR_ . 'css/',
|
||||
@@ -416,20 +432,26 @@ class MprIcons
|
||||
if (stripos($file, 'material') !== false) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
if (stripos($file, 'fontawesome') !== false || stripos($file, 'font-awesome') !== false) {
|
||||
return self::FA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PS 1.6 — check for parent theme name
|
||||
if (defined('_THEME_NAME_')) {
|
||||
$themeName = _THEME_NAME_;
|
||||
if (stripos($themeName, 'hummingbird') !== false) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
// PS 1.6 — check for font-awesome directory
|
||||
$faDir = _PS_THEME_DIR_ . 'css/font-awesome/';
|
||||
if (is_dir($faDir)) {
|
||||
return self::FA;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Detection failed — use safe default
|
||||
}
|
||||
|
||||
// Safe default: FA for PS 1.6, Material for 1.7+
|
||||
if (defined('_PS_VERSION_') && version_compare(_PS_VERSION_, '1.7.0.0', '>=')) {
|
||||
return self::MATERIAL;
|
||||
}
|
||||
|
||||
return self::FA;
|
||||
}
|
||||
|
||||
@@ -444,8 +466,30 @@ class MprIcons
|
||||
}
|
||||
|
||||
$iconSet = self::getIconSet();
|
||||
$needle = ($iconSet === self::MATERIAL) ? 'Material Icons' : 'FontAwesome';
|
||||
|
||||
try {
|
||||
// Check compiled theme CSS — icons are typically bundled here
|
||||
$cssFiles = [
|
||||
_PS_THEME_DIR_ . 'assets/css/theme.css',
|
||||
_PS_THEME_DIR_ . 'css/theme.css',
|
||||
];
|
||||
|
||||
foreach ($cssFiles as $cssFile) {
|
||||
if (!file_exists($cssFile)) {
|
||||
continue;
|
||||
}
|
||||
$handle = fopen($cssFile, 'r');
|
||||
if ($handle) {
|
||||
$chunk = fread($handle, 51200);
|
||||
fclose($handle);
|
||||
if (stripos($chunk, $needle) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for separate icon CSS files
|
||||
$dirs = [
|
||||
_PS_THEME_DIR_ . 'assets/css/',
|
||||
_PS_THEME_DIR_ . 'css/',
|
||||
@@ -455,34 +499,25 @@ class MprIcons
|
||||
if (!is_dir($dir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$files = scandir($dir);
|
||||
foreach ($files as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($iconSet === self::MATERIAL) {
|
||||
if (stripos($file, 'material') !== false) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (stripos($file, 'fontawesome') !== false || stripos($file, 'font-awesome') !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($iconSet === self::MATERIAL && stripos($file, 'material') !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($iconSet === self::FA && (stripos($file, 'fontawesome') !== false || stripos($file, 'font-awesome') !== false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For Font Awesome — most PS 1.6/1.7 themes include it as a dependency
|
||||
// Check if theme's package.json or theme.yml lists it
|
||||
// PS 1.6 — check for font-awesome directory
|
||||
if ($iconSet === self::FA) {
|
||||
$themeYml = _PS_THEME_DIR_ . 'config/theme.yml';
|
||||
if (file_exists($themeYml)) {
|
||||
$content = file_get_contents($themeYml);
|
||||
if (stripos($content, 'font-awesome') !== false || stripos($content, 'fontawesome') !== false) {
|
||||
return true;
|
||||
}
|
||||
$faDir = _PS_THEME_DIR_ . 'css/font-awesome/';
|
||||
if (is_dir($faDir)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Reference in New Issue
Block a user