From 8ea6df020b8fcff213a22ece396d05896b066b2b Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Thu, 4 Jun 2026 13:50:12 -0500 Subject: [PATCH] refactor: remove branding/identity from core plugin (#154) Remove 8 branding methods and 4 call sites (-428 lines): - enforceAtumBranding(), hexToHsl(), injectFavicon() - enforceLoginSupportUrls(), loadLanguageOverrides() - getPlaceholders(), parseLanguageFile(), setTemplateParam() MokoWaaS is an admin tools suite, not a branding layer. Core plugin docblock updated to reflect new purpose. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Extension/MokoWaaS.php | 436 +----------------- 1 file changed, 4 insertions(+), 432 deletions(-) diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index 86b8a9f6..910b4996 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -24,7 +24,7 @@ * REPO: https://github.com/mokoconsulting-tech/mokowaas * VERSION: 02.33.01 * PATH: /src/Extension/MokoWaaS.php - * NOTE: Handles Joomla system events for rebranding functionality + * NOTE: Core system plugin for MokoWaaS admin tools suite */ namespace Moko\Plugin\System\MokoWaaS\Extension; @@ -42,10 +42,9 @@ use Joomla\CMS\User\UserHelper; use Psr\Container\ContainerInterface; /** - * MokoWaaS Brand System Plugin + * MokoWaaS Core System Plugin * - * This plugin rebrands the Joomla system interface with MokoWaaS identity. - * It applies language overrides and ensures consistent branding across the platform. + * This plugin provides core coordination for the MokoWaaS admin tools suite. * * @since 01.04.00 */ @@ -187,18 +186,14 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface $this->handleMokoApi($mokoAction); } - // Admin-only core controls (branding, emergency access, master user) + // Admin-only core controls (emergency access, master user) // NOTE: enforceHttps, enforceDevMode, enforceAdminSessionTimeout, // enforceUploadRestrictions are now in feature plugins if ($this->app->isClient('administrator')) { $this->handleEmergencyAccess(); $this->enforceMasterUser(); - $this->enforceLoginSupportUrls(); - $this->enforceAtumBranding(); } - - $this->loadLanguageOverrides(); } /** @@ -698,102 +693,6 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface return in_array($clientIp, $allowedIps, true); } - /** - * Build the placeholder → value map from plugin params. - * - * @return array Associative array of placeholder => replacement value - * - * @since 02.01.08 - */ - protected function getPlaceholders() - { - return [ - '{{BRAND_NAME}}' => self::BRAND_NAME, - '{{COMPANY_NAME}}' => self::COMPANY_NAME, - '{{SUPPORT_URL}}' => self::SUPPORT_URL, - ]; - } - - /** - * Load language override templates and inject resolved strings into Joomla. - * - * Reads the override template shipped with the plugin, replaces - * {{BRAND_NAME}}, {{COMPANY_NAME}} and {{SUPPORT_URL}} with the - * values from plugin params, then injects the resolved strings into - * the active Language object. - * - * @return void - * - * @since 02.01.08 - */ - protected function loadLanguageOverrides() - { - $language = $this->app->getLanguage(); - $tag = $language->getTag(); - $pluginPath = JPATH_PLUGINS . '/system/mokowaas'; - $isAdmin = $this->app->isClient('administrator'); - - $overridePath = $isAdmin - ? $pluginPath . '/administrator/language/overrides/' . $tag . '.override.ini' - : $pluginPath . '/language/overrides/' . $tag . '.override.ini'; - - if (!file_exists($overridePath)) - { - return; - } - - $strings = $this->parseLanguageFile($overridePath); - $placeholders = $this->getPlaceholders(); - - foreach ($strings as $key => $value) - { - $language->_strings[$key] = str_replace( - array_keys($placeholders), - array_values($placeholders), - $value - ); - } - } - - /** - * Parse a language INI file and return the raw strings (with placeholders). - * - * @param string $filePath The path to the language file - * - * @return array Array of language strings (key => raw value) - * - * @since 02.01.08 - */ - protected function parseLanguageFile($filePath) - { - $strings = []; - - if (!file_exists($filePath)) - { - return $strings; - } - - $content = file_get_contents($filePath); - $lines = explode("\n", $content); - - foreach ($lines as $line) - { - $line = trim($line); - - if ($line === '' || $line[0] === ';') - { - continue; - } - - if (preg_match('/^([A-Z0-9_]+)="(.+)"$/i', $line, $matches)) - { - $strings[strtoupper($matches[1])] = $matches[2]; - } - } - - return $strings; - } - /** * Event triggered after an extension's config is saved. * @@ -1044,7 +943,6 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface return; } - $this->injectFavicon($doc); $this->redirectHelpMenu($doc); // Hide MokoWaaS from plugin list for non-master users @@ -4419,115 +4317,7 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface * @since 02.01.08 */ - /** - * Set a parameter on a template style. - * - * @param string $template Template element name - * @param string $key Parameter key - * @param mixed $value Parameter value - * - * @return void - * - * @since 02.31.00 - */ - private function setTemplateParam(string $template, string $key, $value): void - { - try - { - $db = Factory::getDbo(); - $query = $db->getQuery(true) - ->select([$db->quoteName('id'), $db->quoteName('params')]) - ->from($db->quoteName('#__template_styles')) - ->where($db->quoteName('template') . ' = ' . $db->quote($template)); - $db->setQuery($query); - $styles = $db->loadObjectList(); - foreach ($styles as $style) - { - $params = new \Joomla\Registry\Registry($style->params ?: '{}'); - - if ($params->get($key) != $value) - { - $params->set($key, $value); - - $db->setQuery( - $db->getQuery(true) - ->update($db->quoteName('#__template_styles')) - ->set($db->quoteName('params') . ' = ' . $db->quote($params->toString())) - ->where($db->quoteName('id') . ' = ' . (int) $style->id) - )->execute(); - } - } - } - catch (\Throwable $e) - { - // Silent - } - } - - /** - * Enforce login support module URLs on admin requests. - * - * Checks the mod_loginsupport module params and corrects them if - * they have been changed away from the expected values. - * - * @return void - * - * @since 02.01.08 - */ - protected function enforceLoginSupportUrls() - { - $expected = [ - 'forum_url' => 'https://mokoconsulting.tech/support', - 'documentation_url' => 'https://mokoconsulting.tech/kb', - 'news_url' => 'https://mokoconsulting.tech/news', - ]; - - $db = Factory::getDbo(); - $query = $db->getQuery(true) - ->select([$db->quoteName('id'), $db->quoteName('params')]) - ->from($db->quoteName('#__modules')) - ->where($db->quoteName('module') . ' = ' - . $db->quote('mod_loginsupport')); - - $db->setQuery($query); - $modules = $db->loadObjectList(); - - if (empty($modules)) - { - return; - } - - foreach ($modules as $module) - { - $params = new \Joomla\Registry\Registry( - $module->params ?: '{}' - ); - $needsFix = false; - - foreach ($expected as $key => $url) - { - if ($params->get($key) !== $url) - { - $params->set($key, $url); - $needsFix = true; - } - } - - if ($needsFix) - { - $update = $db->getQuery(true) - ->update($db->quoteName('#__modules')) - ->set($db->quoteName('params') . ' = ' - . $db->quote($params->toString())) - ->where($db->quoteName('id') . ' = ' - . (int) $module->id); - - $db->setQuery($update); - $db->execute(); - } - } - } // ------------------------------------------------------------------ // Tenant Restrictions (called from onAfterRoute) @@ -4584,224 +4374,6 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface return $this->masterNames; } - // ------------------------------------------------------------------ - // Atum Template Branding (called from onAfterInitialise) - // ------------------------------------------------------------------ - /** - * Enforce Atum admin template branding params. - * - * Sets logoBrandLarge, logoBrandSmall, loginLogo, and alt text - * in the Atum template style params. Uses the plugin's media - * folder as the image source. Only writes to DB when values - * have drifted. - * - * @return void - * - * @since 02.01.08 - */ - protected function enforceAtumBranding() - { - $mediaBase = 'media/plg_system_mokowaas/'; - - // Logo params - $expected = [ - 'logoBrandLarge' => $mediaBase . 'logo.png', - 'logoBrandSmall' => $mediaBase . 'favicon_256.png', - 'loginLogo' => $mediaBase . 'logo.png', - 'logoBrandLargeAlt' => '', - 'logoBrandSmallAlt' => '', - 'loginLogoAlt' => '', - 'emptyLogoBrandLargeAlt' => '1', - 'emptyLogoBrandSmallAlt' => '1', - 'emptyLoginLogoAlt' => '1', - ]; - - // Hardcoded color scheme - $primary = self::COLOR_PRIMARY; - $sidebar = self::COLOR_SIDEBAR; - $link = self::COLOR_LINK; - - if (!empty($primary)) - { - // Convert hex to HSL for Atum's hue param - $hsl = $this->hexToHsl($primary); - - if ($hsl) - { - $expected['hue'] = sprintf( - 'hsl(%d, %d%%, %d%%)', - $hsl[0], $hsl[1], $hsl[2] - ); - } - - $expected['special-color'] = $primary; - } - - if (!empty($sidebar)) - { - $expected['header-color'] = $sidebar; - } - - if (!empty($link)) - { - $expected['link-color'] = $link; - } - - $db = Factory::getDbo(); - $query = $db->getQuery(true) - ->select([$db->quoteName('id'), $db->quoteName('params')]) - ->from($db->quoteName('#__template_styles')) - ->where($db->quoteName('template') . ' = ' - . $db->quote('atum')) - ->where($db->quoteName('client_id') . ' = 1'); - - $db->setQuery($query); - $styles = $db->loadObjectList(); - - if (empty($styles)) - { - return; - } - - foreach ($styles as $style) - { - $params = new \Joomla\Registry\Registry( - $style->params ?: '{}' - ); - $needsFix = false; - - foreach ($expected as $key => $value) - { - if ($params->get($key) !== $value) - { - $params->set($key, $value); - $needsFix = true; - } - } - - if ($needsFix) - { - $update = $db->getQuery(true) - ->update($db->quoteName('#__template_styles')) - ->set($db->quoteName('params') . ' = ' - . $db->quote($params->toString())) - ->where($db->quoteName('id') . ' = ' - . (int) $style->id); - - $db->setQuery($update); - $db->execute(); - } - } - } - - /** - * Convert a hex color to HSL values. - * - * @param string $hex Hex color (e.g., "#1a2744") - * - * @return array|null [hue, saturation%, lightness%] or null - * - * @since 02.01.08 - */ - protected function hexToHsl($hex) - { - $hex = ltrim($hex, '#'); - - if (strlen($hex) !== 6) - { - return null; - } - - $r = hexdec(substr($hex, 0, 2)) / 255; - $g = hexdec(substr($hex, 2, 2)) / 255; - $b = hexdec(substr($hex, 4, 2)) / 255; - - $max = max($r, $g, $b); - $min = min($r, $g, $b); - $l = ($max + $min) / 2; - - if ($max === $min) - { - return [0, 0, (int) round($l * 100)]; - } - - $d = $max - $min; - $s = $l > 0.5 - ? $d / (2 - $max - $min) - : $d / ($max + $min); - - if ($max === $r) - { - $h = ($g - $b) / $d + ($g < $b ? 6 : 0); - } - elseif ($max === $g) - { - $h = ($b - $r) / $d + 2; - } - else - { - $h = ($r - $g) / $d + 4; - } - - $h = $h / 6; - - return [ - (int) round($h * 360), - (int) round($s * 100), - (int) round($l * 100), - ]; - } - - // ------------------------------------------------------------------ - // Visual Branding (called from onBeforeCompileHead) - // ------------------------------------------------------------------ - - /** - * Replace the default favicon with a custom one. - * - * @param \Joomla\CMS\Document\HtmlDocument $doc - * - * @return void - * - * @since 02.01.08 - */ - protected function injectFavicon($doc) - { - $mediaBase = 'media/plg_system_mokowaas/'; - $root = Uri::root(); - - // Remove all existing favicon/icon links - foreach ($doc->_links as $href => $attrs) - { - if (isset($attrs['relation']) - && strpos($attrs['relation'], 'icon') !== false) - { - unset($doc->_links[$href]); - } - } - - // SVG favicon (modern browsers, preferred) - $doc->addHeadLink( - $root . $mediaBase . 'favicon.svg', - 'icon', - 'rel', - ['type' => 'image/svg+xml'] - ); - // ICO fallback (legacy browsers) - $doc->addHeadLink( - $root . $mediaBase . 'favicon.ico', - 'alternate icon', - 'rel', - ['type' => 'image/vnd.microsoft.icon'] - ); - // PNG for Apple/Android - $doc->addHeadLink( - $root . $mediaBase . 'favicon_256.png', - 'apple-touch-icon', - 'rel', - ['sizes' => '256x256'] - ); - } }