<?php
|
namespace JVBase\managers;
|
|
use JVBase\registrar\Registrar;
|
use JVBase\base\Site;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
class IconsManager
|
{
|
// Static array holding all source instances
|
protected static array $instances = [];
|
|
// Static storage for all custom icons across sources
|
protected static array $customIconsRegistry = [];
|
|
// Instance-specific properties
|
protected string $source;
|
protected array $icons = []; // Icons for THIS source [style => [names]]
|
protected Cache $cache;
|
protected string $style = 'regular';
|
protected array $styles = ['regular', 'bold', 'duotone', 'fill', 'light', 'thin'];
|
protected array $customIcons = []; // Custom icons for THIS source
|
protected array $map = [];
|
protected const MAX_VERSIONS = 5;
|
|
/**
|
* Factory method - get or create instance for a source
|
*/
|
public static function for(string $source = 'icons'): IconsManager
|
{
|
if (!isset(self::$instances[$source])) {
|
self::$instances[$source] = new self($source);
|
}
|
return self::$instances[$source];
|
}
|
|
/**
|
* Constructor now takes source parameter
|
*/
|
private function __construct(string $source)
|
{
|
$this->source = $source;
|
$this->cache = Cache::for('icons_' . $source, WEEK_IN_SECONDS);
|
$this->style = Site::icon();
|
|
$this->addMap();
|
|
// Register custom icons only once for all sources
|
if ($source === 'icons') {
|
$this->registerCustomIcons();
|
}
|
|
// Load custom icons for THIS source
|
$this->loadCustomIconsForSource();
|
|
// Load stored icons for this source
|
$this->loadStoredIcons();
|
|
if (empty($this->icons)) {
|
$this->includeIcons();
|
}
|
|
// Register global hooks only once (first instance)
|
if (count(self::$instances) === 1) {
|
$this->registerGlobalHooks();
|
}
|
|
// Register instance's hooks (every instance)
|
$this->registerInstanceHooks();
|
}
|
|
|
|
/**
|
* Register all custom icons (runs once)
|
*/
|
protected function registerCustomIcons(): void
|
{
|
$icons = array_merge(apply_filters('jvbRegisterCustomIcons', []), ['syncing' => JVB_DIR . '/assets/icons/cloud-sync-thin.svg',
|
'alphabetical' => JVB_DIR . '/assets/icons/alphabetical.svg']);
|
|
// Process and store in static property so all instances can access
|
self::$customIconsRegistry = $this->processCustomIconsArray($icons);
|
}
|
|
/**
|
* Process custom icons array into source-grouped format
|
*/
|
protected function processCustomIconsArray(array $icons): array
|
{
|
$out = [];
|
foreach ($icons as $name => $source) {
|
if (!file_exists($source)) {
|
error_log('[IconsManager] No file exists for custom Icon: '.$name);
|
continue;
|
}
|
$out[$name] = $source;
|
}
|
|
return $out;
|
}
|
|
/**
|
* Load custom icons for this instance's source
|
*/
|
protected function loadCustomIconsForSource(): void
|
{
|
$this->customIcons = self::$customIconsRegistry;
|
// foreach ($this->customIcons as $name => $path) {
|
// if (!isset($this->icons[$this->style])) {
|
// $this->icons[$this->style] = [];
|
// }
|
// if (!in_array($name, $this->icons[$this->style])) {
|
// $this->icons[$this->style][] = $name;
|
// }
|
// }
|
}
|
|
/**
|
* Load previously stored icons for this source
|
*/
|
protected function loadStoredIcons(): void
|
{
|
$allIcons = get_option(BASE.'usedIcons', []);
|
$storedIcons = $allIcons[$this->source] ?? [];
|
|
// Merge stored icons with any existing icons (like custom icons)
|
foreach ($storedIcons as $style => $names) {
|
if (!isset($this->icons[$style])) {
|
$this->icons[$style] = [];
|
}
|
$this->icons[$style] = array_unique(array_merge($this->icons[$style], $names));
|
}
|
}
|
|
protected function includeIcons():void
|
{
|
$defaults = [
|
'icons' => [
|
'google-logo',
|
'apple-logo',
|
'check-circle',
|
'close-circle',
|
'cloud-slash',
|
'exclamation-mark',
|
'cloud-arrow-down',
|
'caret-down',
|
'cloud-arrow-up',
|
'cloud-check',
|
'cloud-slash',
|
'cloud-warning',
|
'syncing',
|
'cloud-x',
|
'arrows-clockwise',
|
'share-fat',
|
'trash',
|
'star',
|
'alphabetical',
|
['name' => 'star-half', 'style' => 'fill'],
|
['name' => 'star', 'style' => 'fill'],
|
],
|
'forms' => [
|
'copy',
|
'paragraph',
|
'text-h-one',
|
'text-h-two',
|
'text-h-three',
|
'text-h-four',
|
'text-h-five',
|
'text-h-six',
|
['name' =>'text-b', 'style' => 'fill'],
|
'text-italic',
|
'text-underline',
|
'text-strikethrough',
|
'list-dashes',
|
'list-numbers',
|
'text-align-left',
|
'text-align-center',
|
'text-align-right',
|
// 'text-align-justify',
|
'link',
|
//FILE ICONS
|
'file-pdf',
|
'file-csv',
|
'file-doc',
|
'file-txt',
|
'file-xls',
|
],
|
// 'dash' => [
|
//
|
// ]
|
];
|
|
// Add icons from content/taxonomy/user configs (like old behavior)
|
$configIcons = $this->getIconsFromConfigs();
|
if (!empty($configIcons)) {
|
$defaults['icons'] = array_merge($defaults['icons'], $configIcons);
|
}
|
|
// Allow filtering per source (extensibility)
|
$icons = apply_filters("jvbIncludeIcons_{$this->source}", $defaults[$this->source] ?? []);
|
|
// Also allow filtering all sources at once
|
$allIcons = apply_filters('jvbIncludeIcons', $defaults);
|
if (isset($allIcons[$this->source])) {
|
$icons = array_merge($icons, $allIcons[$this->source]);
|
}
|
|
if (!empty($icons)) {
|
$this->include($icons);
|
}
|
}
|
|
/**
|
* Get icons from Registrar instances
|
*
|
*/
|
protected function getIconsFromConfigs(): array
|
{
|
$icons = [];
|
$registered = Registrar::getRegistered();
|
|
foreach ($registered as $type) {
|
$registrar = Registrar::getInstance($type);
|
$icons[] = $registrar->getIcon();
|
}
|
|
|
return array_unique(array_filter($icons));
|
}
|
|
/**
|
* Public method to include icons in this source
|
*/
|
public function include(array $icons): self
|
{
|
$processed = $this->processIconArray($icons);
|
$changed = false;
|
|
foreach ($processed as $style => $names) {
|
if (!isset($this->icons[$style])) {
|
$this->icons[$style] = [];
|
}
|
|
foreach ($names as $name) {
|
// Skip if already in this source
|
if (in_array($name, $this->icons[$style])) {
|
continue;
|
}
|
|
// Skip if already in main 'icons' source
|
if ($this->iconExistsInMainSource($name, $style)) {
|
error_log("[IconsManager] Skipping '{$name}' in '{$this->source}' - already in 'icons' source");
|
continue;
|
}
|
|
$this->icons[$style][] = $name;
|
$changed = true;
|
}
|
}
|
|
// Only save if something actually changed
|
if ($changed) {
|
$this->saveIcons();
|
}
|
|
return $this;
|
}
|
|
/**
|
* Process icon array into [style => [names]] format
|
*/
|
protected function processIconArray(array $icons): array
|
{
|
$out = [];
|
|
foreach ($icons as $icon) {
|
if (is_array($icon) && isset($icon['style'])) {
|
$style = $icon['style'];
|
$name = $icon['name'];
|
} else {
|
$style = $this->style;
|
$name = is_array($icon) ? $icon['name'] : $icon;
|
}
|
|
if (!isset($out[$style])) {
|
$out[$style] = [];
|
}
|
|
if (!in_array($name, $out[$style])) {
|
$out[$style][] = $name;
|
}
|
}
|
|
return $out;
|
}
|
|
/**
|
* Save all icons across all instances
|
*/
|
protected function saveIcons(): void
|
{
|
$allIcons = [];
|
foreach (self::$instances as $source => $instance) {
|
$allIcons[$source] = $instance->icons;
|
}
|
|
update_option(BASE.'usedIcons', $allIcons);
|
|
// Track WHICH source needs updating
|
$needsUpdate = get_option(BASE.'icons_needs_update', []);
|
if (!is_array($needsUpdate)) {
|
$needsUpdate = [];
|
}
|
$needsUpdate[$this->source] = true;
|
update_option(BASE.'icons_needs_update', $needsUpdate);
|
}
|
|
/**
|
* Check if icon exists in other sources
|
*/
|
protected function checkDuplicateAcrossInstances(string $name, string $style): void
|
{
|
$foundIn = [];
|
|
foreach (self::$instances as $source => $instance) {
|
if (isset($instance->icons[$style]) && in_array($name, $instance->icons[$style])) {
|
$foundIn[] = $source;
|
}
|
}
|
|
if (count($foundIn) > 1) {
|
error_log(sprintf(
|
'[IconsManager] Warning: Icon "%s" (%s) is registered in multiple sources: %s. Consider consolidating to avoid duplicate CSS output.',
|
$name,
|
$style,
|
implode(', ', $foundIn)
|
));
|
}
|
}
|
|
protected function addMap(): void
|
{
|
$map = get_option(BASE.'iconMap');
|
if (!$map) {
|
$map = [
|
'seo' => 'robot'
|
];
|
if (Site::has('referrals')) {
|
$map['referrals'] = 'hand-heart';
|
}
|
if (Site::has('dashboard')) {
|
$map['dash'] = 'door';
|
}
|
if (Site::has('magicLink')) {
|
$map['magicLink'] = 'magic-wand';
|
}
|
if (Site::hasAnyIntegration()) {
|
$map['integrations'] = 'plugs-connected';
|
}
|
update_option(BASE.'iconMap', $map);
|
}
|
|
$this->map = apply_filters('jvbMapIcons', $map);
|
}
|
|
/**
|
* Register global hooks (only once)
|
*/
|
protected function registerGlobalHooks(): void
|
{
|
add_action('wp_loaded', [self::class, 'checkCSS']);
|
}
|
|
/**
|
* Register instance-specific hooks (every instance)
|
*/
|
protected function registerInstanceHooks(): void
|
{
|
// Register this source's stylesheet
|
add_action('init', [$this, 'registerStyle'], 11);
|
|
// Auto-enqueue base icons on front-end
|
if ($this->source === 'icons') {
|
add_action('wp_enqueue_scripts', [$this, 'enqueueIconStyles']);
|
}
|
|
// Auto-enqueue all in admin
|
add_action('admin_enqueue_scripts', [$this, 'enqueueIconStyles']);
|
}
|
|
public function enqueueIconStyles():void
|
{
|
// if (file_exists(JVB_CHILD_URL . "assets/css/{$this->source}.css")){
|
wp_enqueue_style('jvb-icons-'.$this->source);
|
// }
|
|
}
|
|
public static function checkCSS(): void
|
{
|
$needsUpdate = get_option(BASE.'icons_needs_update', []);
|
if (!empty($needsUpdate)) {
|
error_log('Regenerating CSS for sources: ' . implode(', ', array_keys($needsUpdate)));
|
delete_option(BASE.'icons_needs_update');
|
self::regenerateAllCSS($needsUpdate);
|
}
|
}
|
|
public static function regenerateAllCSS(array $sourcesToUpdate = []): void
|
{
|
error_log('[IconsManager]:regenerateCSS');
|
$css_dir = JVB_CHILD_DIR.'/assets/css/';
|
|
if (!file_exists($css_dir)) {
|
wp_mkdir_p($css_dir);
|
}
|
|
// Load all icons from database option
|
$allIcons = get_option(BASE.'usedIcons', []);
|
|
// If no specific sources provided, regenerate all
|
if (empty($sourcesToUpdate)) {
|
$sourcesToUpdate = array_fill_keys(array_keys($allIcons), true);
|
}
|
|
// Generate CSS for each source that needs it
|
foreach ($sourcesToUpdate as $source => $needsUpdate) {
|
if (!$needsUpdate || !isset($allIcons[$source])) {
|
continue;
|
}
|
|
// Get or create instance for this source
|
$instance = self::for($source);
|
|
// Temporarily set icons from database
|
$originalIcons = $instance->icons;
|
$instance->icons = $allIcons[$source];
|
|
$css = $instance->generateIconCSS();
|
$css_path = $css_dir . $source . '.css';
|
|
$instance->archiveCurrentVersion($css);
|
|
if (file_put_contents($css_path, $css) !== false) {
|
Cache::touch('icons_' . $source);
|
error_log("[IconsManager] Updated {$source}.css");
|
} else {
|
error_log("[IconsManager] Could not write {$source}.css");
|
}
|
|
// Restore original icons
|
$instance->icons = $originalIcons;
|
}
|
}
|
|
protected function regenerateCSS(array $sourcesToUpdate = []): void
|
{
|
error_log('[IconsManager]:regenerateCSS');
|
$css_dir = JVB_CHILD_DIR.'/assets/css/';
|
|
if (!file_exists($css_dir)) {
|
wp_mkdir_p($css_dir);
|
}
|
|
// If no specific sources provided, regenerate all
|
if (empty($sourcesToUpdate)) {
|
$sourcesToUpdate = array_fill_keys(array_keys(self::$instances), true);
|
}
|
|
// Generate CSS only for sources that need it
|
foreach (self::$instances as $source => $instance) {
|
if (!isset($sourcesToUpdate[$source])) {
|
continue; // Skip this source
|
}
|
|
$css = $instance->generateIconCSS();
|
$css_path = $css_dir . $source . '.css';
|
|
// Archive current version before overwriting
|
$instance->archiveCurrentVersion($css);
|
|
if (file_put_contents($css_path, $css) !== false) {
|
Cache::touch('icons_' . $source);
|
error_log("[IconsManager] Updated {$source}.css");
|
} else {
|
error_log("[IconsManager] Could not write {$source}.css");
|
}
|
}
|
}
|
|
/**
|
* Prevent cloning
|
*/
|
private function __clone() {}
|
|
/**
|
* Prevent unserialization
|
*/
|
public function __wakeup()
|
{
|
throw new \Exception("Cannot unserialize singleton");
|
}
|
|
/**
|
* Get an icon element
|
*
|
* @param string $name Icon name (e.g., 'heart', 'calendar')
|
* @param array $options Options array:
|
* - 'style' => 'regular'|'bold'|'fill'|etc.
|
* - 'label' => 'Accessible label' (for standalone icons)
|
* - 'decorative' => true (for icons next to text)
|
* - 'class' => 'additional classes'
|
* - 'size' => 24 (for custom sizing via inline style)
|
* @return string HTML icon element
|
*/
|
public function get(string $name, array $options = []): string
|
{
|
if (empty($name)) {
|
//No icon requested
|
return '';
|
}
|
$style = $options['style'] ?? $this->style;
|
$name = $this->map[$name] ?? $name;
|
|
// Validate icon exists
|
if (!$this->iconExists($name, $style)) {
|
error_log('[IconsManager] Icon not found: ' . $name);
|
return '';
|
}
|
|
// Track usage - only if not already tracked
|
if (!isset($this->icons[$style])) {
|
$this->icons[$style] = [];
|
}
|
|
if (!in_array($name, $this->icons[$style])) {
|
// Check if it's already in main source (for non-main sources)
|
if ($this->iconExistsInMainSource($name, $style)) {
|
// Don't add to this source, but still render the icon
|
// The CSS from icons.css will handle it
|
} else {
|
// Add to this source
|
$this->icons[$style][] = $name;
|
$this->checkDuplicateAcrossInstances($name, $style);
|
$this->saveIcons();
|
}
|
}
|
|
// Build icon HTML (same as before)
|
$styleClass = ($style !== $this->style) ? '-'.substr($style, 0, 2) : '';
|
$classes = ['icon', 'icon-' . $name.$styleClass];
|
|
if (isset($options['class'])) {
|
$classes[] = $options['class'];
|
}
|
|
$attrs = ['class' => implode(' ', $classes)];
|
|
if (isset($options['label'])) {
|
$attrs['aria-label'] = esc_attr($options['label']);
|
$attrs['role'] = 'img';
|
} elseif (isset($options['decorative']) && $options['decorative']) {
|
$attrs['aria-hidden'] = 'true';
|
}
|
|
if (isset($options['size'])) {
|
$attrs['style'] = sprintf('--icon-size: %dpx;', absint($options['size']));
|
}
|
|
$attr_string = '';
|
foreach ($attrs as $key => $value) {
|
$attr_string .= sprintf(' %s="%s"', $key, $value);
|
}
|
|
return sprintf('<i%s></i>', $attr_string);
|
}
|
|
/**
|
* Check if icon file exists
|
*/
|
protected function iconExists(string $name, ?string $style = null): bool
|
{
|
if (!$style) {
|
$style = $this->style;
|
}
|
// Check custom icons first
|
if (array_key_exists($name, $this->customIcons)) {
|
return file_exists($this->customIcons[$name]);
|
}
|
|
// Check standard icons
|
$filepath = $this->buildFilePath($name, $style);
|
return file_exists($filepath);
|
}
|
|
/**
|
* Build file path for icon
|
*/
|
protected function buildFilePath(string $name, ?string $style = null): string
|
{
|
if (!$style) {
|
$style = $this->style;
|
}
|
// Custom icons (absolute path provided)
|
if (array_key_exists($name, $this->customIcons)) {
|
return $this->customIcons[$name];
|
}
|
|
// Standard SVG icons in /assets/icons/
|
if (str_ends_with($name, '.svg')) {
|
return JVB_DIR . '/assets/icons/' . $name;
|
}
|
$name = ($style === 'regular') ? $name : $name . '-' . $style;
|
|
// Phosphor icons with style variants
|
return JVB_DIR . '/assets/phosphor-icons/' . $style . '/' . $name . '.svg';
|
}
|
|
/**
|
* Get raw SVG content for CSS mask-image
|
*/
|
protected function getRawSvg(string $name, ?string $style = null): ?string
|
{
|
if (!$style) {
|
$style = $this->style;
|
}
|
$filepath = $this->buildFilePath($name, $style);
|
|
if (!file_exists($filepath)) {
|
return null;
|
}
|
|
$svg = file_get_contents($filepath);
|
if ($svg === false) {
|
return null;
|
}
|
|
// Clean up SVG for CSS usage
|
$svg = preg_replace("/([\n\t]+)/", ' ', $svg);
|
$svg = preg_replace('/>\s*</', '><', $svg);
|
return trim($svg);
|
}
|
|
public function registerStyle(): void
|
{
|
$timestamp = Cache::lastModified('icons_' . $this->source);
|
$handle = 'jvb-icons-' . $this->source;
|
|
wp_register_style(
|
$handle,
|
JVB_CHILD_URL . "assets/css/{$this->source}.css",
|
[],
|
$timestamp
|
);
|
}
|
|
/**
|
* Generate CSS from icon list
|
*/
|
protected function generateIconCSS(): string
|
{
|
$css = '';
|
|
foreach ($this->icons as $style => $names) {
|
$styleClass = ($style !== $this->style) ? '-'.substr($style, 0, 2) : '';
|
foreach ($names as $icon) {
|
$svg = $this->getEncodedSVG($icon, $style);
|
if ($svg !== '') {
|
$css .= ".icon-{$icon}{$styleClass}{";
|
$css .= "--icon:url('data:image/svg+xml;base64,{$svg}');";
|
$css .= "}";
|
}
|
}
|
}
|
|
return $this->minifyCss($css);
|
}
|
|
protected function minifyCSS(string $css): string
|
{
|
// Remove comments
|
$css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
|
// Remove whitespace
|
$css = preg_replace('/\s+/', ' ', $css);
|
// Remove spaces around specific characters
|
$css = preg_replace('/\s*([:;{}])\s*/', '$1', $css);
|
|
return trim($css);
|
}
|
|
public function getCSSIcon(string $icon, ?string $style = null): string
|
{
|
if (!$style) {
|
$style = $this->style;
|
}
|
|
$icon = $this->map[$icon] ?? $icon;
|
|
// Validate icon exists
|
if (!$this->iconExists($icon, $style)) {
|
error_log('[IconsManager] Icon not found: ' . $icon);
|
return '';
|
}
|
$svg = $this->getEncodedSVG($icon, $style);
|
if ($svg !== '') {
|
return "data:image/svg+xml;base64,{$svg}";
|
}
|
return '';
|
}
|
|
public function getEncodedSVG(string $icon, ?string $style = null): string
|
{
|
if (!$style) {
|
$style = $this->style;
|
}
|
return $this->cache->remember($style.$icon,
|
function () use ($icon, $style) {
|
$svg = $this->getRawSvg($icon, $style);
|
if ($svg) {
|
return base64_encode($svg);
|
}
|
return '';
|
});
|
}
|
|
/**
|
* Clear icon cache (useful for development/debugging)
|
*/
|
public function clearIconCache(): void
|
{
|
delete_option(BASE . 'icon_usage_list'); // Legacy
|
delete_option(BASE.'usedIcons');
|
delete_option(BASE.'iconMap');
|
|
// Clear cache for all sources
|
foreach (self::$instances as $source => $instance) {
|
$instance->cache->forget('icon_styles_css');
|
}
|
}
|
|
protected function archiveCurrentVersion(string $css): void
|
{
|
$history = $this->getVersionHistory();
|
|
$icon_count = 0;
|
foreach ($this->icons as $style => $names) {
|
$icon_count += count($names);
|
}
|
|
$newEntry = [
|
'css' => $css,
|
'iconList' => $this->icons,
|
'timestamp' => time(),
|
'icon_count' => $icon_count,
|
'size' => strlen($css),
|
'size_formatted' => size_format(strlen($css), 2)
|
];
|
|
array_unshift($history, $newEntry);
|
|
if (count($history) > self::MAX_VERSIONS) {
|
$history = array_slice($history, 0, self::MAX_VERSIONS);
|
}
|
|
update_option(BASE.'icon_css_history_' . $this->source, $history);
|
}
|
|
public function getVersionHistory(): array
|
{
|
return get_option(BASE.'icon_css_history_' . $this->source, []);
|
}
|
|
public function restoreVersion(int $timestamp): bool
|
{
|
$history = $this->getVersionHistory();
|
|
foreach ($history as $entry) {
|
if ($entry['timestamp'] === $timestamp) {
|
$css_path = JVB_CHILD_DIR . '/assets/css/' . $this->source . '.css';
|
|
// Archive current before restoring
|
$current_css = file_get_contents($css_path);
|
if ($current_css !== false) {
|
$this->archiveCurrentVersion($current_css);
|
}
|
|
// Restore the version
|
if (file_put_contents($css_path, $entry['css']) !== false) {
|
$this->icons = $entry['iconList'];
|
$this->saveIcons();
|
Cache::touch('icons_' . $this->source);
|
return true;
|
}
|
|
return false;
|
}
|
}
|
|
error_log("[IconsManager] Version {$timestamp} not found in history for source {$this->source}");
|
return false;
|
}
|
|
public function forceRefresh(): void
|
{
|
$this->clearIconCache();
|
$needsUpdate = get_option(BASE.'icons_needs_update', []);
|
if (!is_array($needsUpdate)) {
|
$needsUpdate = [];
|
}
|
$needsUpdate[$this->source] = true;
|
update_option(BASE.'icons_needs_update', $needsUpdate);
|
Cache::touch('icons_' . $this->source);
|
}
|
|
public function mergeVersions(array $timestamps): bool
|
{
|
if (empty($timestamps)) {
|
return false;
|
}
|
|
$history = get_option(BASE.'icon_css_history_' . $this->source, []);
|
$merged_icons = [];
|
|
// Collect icons from selected versions
|
foreach ($history as $entry) {
|
if (in_array($entry['timestamp'], $timestamps)) {
|
foreach ($entry['iconList'] as $style => $icons) {
|
if (!isset($merged_icons[$style])) {
|
$merged_icons[$style] = [];
|
}
|
// Merge and keep unique
|
$merged_icons[$style] = array_unique(
|
array_merge($merged_icons[$style], $icons)
|
);
|
}
|
}
|
}
|
|
if (empty($merged_icons)) {
|
error_log('[IconsManager] No icons found in selected versions');
|
return false;
|
}
|
|
// Archive current version
|
$current_css = file_get_contents(JVB_CHILD_DIR . '/assets/css/' . $this->source . '.css');
|
if ($current_css !== false) {
|
$this->archiveCurrentVersion($current_css);
|
}
|
|
// Update used icons and regenerate
|
$this->icons = $merged_icons;
|
$this->saveIcons();
|
|
return true;
|
}
|
|
/**
|
* Check if icon already exists in the main 'icons' source
|
*/
|
protected function iconExistsInMainSource(string $name, string $style): bool
|
{
|
// If this IS the main source, no need to check
|
if ($this->source === 'icons') {
|
return false;
|
}
|
|
// Check if main icons source exists
|
if (!isset(self::$instances['icons'])) {
|
return false;
|
}
|
|
$mainIcons = self::$instances['icons']->icons;
|
return isset($mainIcons[$style]) && in_array($name, $mainIcons[$style]);
|
}
|
}
|