refactor: restructure from package back to standalone module #63
@@ -32,26 +32,21 @@ composer install # Install PHP dependencies
|
||||
|
||||
## Architecture
|
||||
|
||||
This is a Joomla **package** extension (`pkg_mokojoomhero`) containing two sub-extensions:
|
||||
This is a Joomla **site module** (`mod_mokojoomhero`).
|
||||
|
||||
### mod_mokojoomhero (Site Module)
|
||||
- Random hero image slideshow or background video with content overlay
|
||||
- Supports image folders, YouTube, Vimeo, local video, solid colour, gradient
|
||||
- Configurable overlay, text alignment, card animation, parallax, content animations
|
||||
- Works independently — no plugin dependency required
|
||||
|
||||
### plg_system_mokojoomhero (System Plugin)
|
||||
- License check — free tier (no key required), pro tier warns if download key missing
|
||||
- Controlled by `LICENSE_TYPE` constant ('free' or 'pro') in the Extension class
|
||||
- Auto-enabled on package install via `pkg_script.php`
|
||||
- Namespace: `Joomla\Plugin\System\MokoJoomHero`
|
||||
- A/B testing with weighted variations, scheduling with start/end datetime
|
||||
- Article content source, per-slide unique content via subform
|
||||
|
||||
### Key files
|
||||
- `src/pkg_mokojoomhero.xml` — package manifest
|
||||
- `src/pkg_script.php` — auto-enables system plugin on install
|
||||
- `src/packages/mod_mokojoomhero/` — hero module source
|
||||
- `src/packages/plg_system_mokojoomhero/` — system plugin source
|
||||
- `updates.xml` — Joomla update server (includes legacy module entries for migration)
|
||||
- `src/mod_mokojoomhero.xml` — module manifest
|
||||
- `src/mod_mokojoomhero.php` — module entry point
|
||||
- `src/tmpl/default.php` — template
|
||||
- `src/media/` — CSS, JS, and web asset registry
|
||||
- `src/language/` — en-GB and en-US translations
|
||||
- `src/script.php` — install script (creates default image folder)
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -66,7 +61,4 @@ This is a Joomla **package** extension (`pkg_mokojoomhero`) containing two sub-e
|
||||
## Coding Standards
|
||||
|
||||
- PHP 8.1+ minimum
|
||||
- Joomla 5/6 DI container pattern: `services/provider.php` → Extension class
|
||||
- Legacy stub `.php` file required for plugin loader but empty
|
||||
- `SubscriberInterface` for event subscription (not `on*` method naming)
|
||||
- SPDX license headers on all PHP files
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
# Extension Configuration
|
||||
EXTENSION_NAME := mokojoomhero
|
||||
EXTENSION_TYPE := package
|
||||
EXTENSION_TYPE := module
|
||||
# Options: module, plugin, component, package, template
|
||||
EXTENSION_VERSION := 1.0.0
|
||||
|
||||
@@ -156,29 +156,11 @@ clean: ## Clean build artifacts
|
||||
|
||||
.PHONY: build
|
||||
build: clean ## Build extension package
|
||||
@echo "$(COLOR_BLUE)Building Joomla package extension...$(COLOR_RESET)"
|
||||
@mkdir -p $(DIST_DIR) $(BUILD_DIR)/packages
|
||||
|
||||
@# --- Build each sub-extension as a separate ZIP ---
|
||||
@for EXT_DIR in $(SRC_DIR)/packages/*/; do \
|
||||
EXT_NAME=$$(basename "$$EXT_DIR"); \
|
||||
[ "$$EXT_NAME" = "index.html" ] && continue; \
|
||||
echo " Packaging $$EXT_NAME..."; \
|
||||
cd "$$EXT_DIR" && $(ZIP) -r "$(CURDIR)/$(BUILD_DIR)/packages/$${EXT_NAME}.zip" . \
|
||||
-x "*.git*" -x "*/index.html" 2>/dev/null; \
|
||||
cd "$(CURDIR)"; \
|
||||
done
|
||||
|
||||
@# --- Build the outer package ZIP ---
|
||||
@echo " Assembling pkg_$(EXTENSION_NAME)..."
|
||||
@cp $(SRC_DIR)/pkg_mokojoomhero.xml $(BUILD_DIR)/pkg_mokojoomhero.xml
|
||||
@cp $(SRC_DIR)/pkg_script.php $(BUILD_DIR)/pkg_script.php
|
||||
@cd $(BUILD_DIR) && $(ZIP) -r "$(CURDIR)/$(DIST_DIR)/pkg_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip" \
|
||||
pkg_mokojoomhero.xml pkg_script.php packages/
|
||||
|
||||
@echo "$(COLOR_GREEN)✓ Package created: $(DIST_DIR)/pkg_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip$(COLOR_RESET)"
|
||||
@echo " Contents:"
|
||||
@unzip -l "$(DIST_DIR)/pkg_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip" | tail -n +4 | head -20
|
||||
@echo "$(COLOR_BLUE)Building Joomla module extension...$(COLOR_RESET)"
|
||||
@mkdir -p $(DIST_DIR)
|
||||
@cd $(SRC_DIR) && $(ZIP) -r "$(CURDIR)/$(DIST_DIR)/mod_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip" . \
|
||||
-x "*.git*" -x "*/index.html" 2>/dev/null
|
||||
@echo "$(COLOR_GREEN)✓ Module created: $(DIST_DIR)/mod_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip$(COLOR_RESET)"
|
||||
|
||||
.PHONY: package
|
||||
package: build ## Alias for build
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@
|
||||
* DEFGROUP: MokoJoomHero.Module.Assets
|
||||
* INGROUP: MokoJoomHero.Module
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
|
||||
* PATH: /src/packages/mod_mokojoomhero/media/css/mod_mokojoomhero.css
|
||||
* VERSION: 01.12.00
|
||||
* PATH: /src/media/css/mod_mokojoomhero.css
|
||||
* VERSION: 01.10.00
|
||||
* BRIEF: Hero module stylesheet — slideshow, video, colour/gradient, overlay, card, mute toggle, responsive
|
||||
*/
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@
|
||||
* DEFGROUP: MokoJoomHero.Module.Assets
|
||||
* INGROUP: MokoJoomHero.Module
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
|
||||
* PATH: /src/packages/mod_mokojoomhero/media/js/mod_mokojoomhero.js
|
||||
* VERSION: 01.12.00
|
||||
* PATH: /src/media/js/mod_mokojoomhero.js
|
||||
* VERSION: 01.10.00
|
||||
* BRIEF: Hero module JavaScript — slideshow crossfade, video viewport control, mute toggle
|
||||
*/
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
DEFGROUP: MokoJoomHero.Module
|
||||
INGROUP: MokoJoomHero
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
|
||||
PATH: /src/packages/mod_mokojoomhero/mod_mokojoomhero.xml
|
||||
PATH: /src/mod_mokojoomhero.xml
|
||||
VERSION: 01.00.20
|
||||
BRIEF: Joomla module manifest — random hero image with content overlay
|
||||
-->
|
||||
<extension type="module" client="site" method="upgrade">
|
||||
<name>Module - MokoJoomHero</name>
|
||||
<creationDate>2026-05</creationDate>
|
||||
<creationDate>2026-06-04</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1,2 +0,0 @@
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -1,5 +0,0 @@
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
PLG_SYSTEM_MOKOJOOMHERO="System - MokoJoomHero"
|
||||
PLG_SYSTEM_MOKOJOOMHERO_DESCRIPTION="System plugin for MokoJoomHero — license and update management"
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1,2 +0,0 @@
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -1,5 +0,0 @@
|
||||
; Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
PLG_SYSTEM_MOKOJOOMHERO="System - MokoJoomHero"
|
||||
PLG_SYSTEM_MOKOJOOMHERO_DESCRIPTION="System plugin for MokoJoomHero — license and update management"
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package MokoJoomHero
|
||||
* @subpackage plg_system_mokojoomhero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* @package MokoJoomHero
|
||||
* @subpackage plg_system_mokojoomhero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
-->
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>PLG_SYSTEM_MOKOJOOMHERO</name>
|
||||
<version>01.12.00</version>
|
||||
<creationDate>2026-06-02</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>PLG_SYSTEM_MOKOJOOMHERO_DESCRIPTION</description>
|
||||
|
||||
<namespace path="src">Joomla\Plugin\System\MokoJoomHero</namespace>
|
||||
|
||||
<files>
|
||||
<filename plugin="mokojoomhero">mokojoomhero.php</filename>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
</files>
|
||||
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/plg_system_mokojoomhero.ini</language>
|
||||
<language tag="en-GB">en-GB/plg_system_mokojoomhero.sys.ini</language>
|
||||
<language tag="en-US">en-US/plg_system_mokojoomhero.ini</language>
|
||||
<language tag="en-US">en-US/plg_system_mokojoomhero.sys.ini</language>
|
||||
</languages>
|
||||
</extension>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package MokoJoomHero
|
||||
* @subpackage plg_system_mokojoomhero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\PluginInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Plugin\System\MokoJoomHero\Extension\MokoJoomHero;
|
||||
|
||||
return new class implements ServiceProviderInterface {
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->set(
|
||||
PluginInterface::class,
|
||||
function (Container $container) {
|
||||
$plugin = new MokoJoomHero(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('system', 'mokojoomhero')
|
||||
);
|
||||
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,100 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package MokoJoomHero
|
||||
* @subpackage plg_system_mokojoomhero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\System\MokoJoomHero\Extension;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
|
||||
class MokoJoomHero extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
/**
|
||||
* License type: 'free' requires no key, 'pro' requires a valid download key.
|
||||
*/
|
||||
private const LICENSE_TYPE = 'free';
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onAfterRoute' => 'onAfterRoute',
|
||||
];
|
||||
}
|
||||
|
||||
public function onAfterRoute(): void
|
||||
{
|
||||
$app = $this->getApplication();
|
||||
|
||||
if ($app->isClient('administrator')) {
|
||||
$this->checkLicense();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check license status once per session. Free tier requires no key.
|
||||
* Pro tier warns if no valid download key is configured.
|
||||
*/
|
||||
private function checkLicense(): void
|
||||
{
|
||||
if (self::LICENSE_TYPE === 'free') {
|
||||
return;
|
||||
}
|
||||
|
||||
$session = Factory::getSession();
|
||||
|
||||
if ($session->get('mokojoomhero.license_checked', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = Factory::getUser();
|
||||
|
||||
if ($user->guest || !$user->authorise('core.manage')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$session->set('mokojoomhero.license_checked', true);
|
||||
|
||||
try {
|
||||
$db = Factory::getDbo();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extra_query'))
|
||||
->from($db->quoteName('#__update_sites'))
|
||||
->where($db->quoteName('name') . ' = ' . $db->quote('MokoJoomHero Updates'))
|
||||
->setLimit(1);
|
||||
$db->setQuery($query);
|
||||
$extraQuery = (string) $db->loadResult();
|
||||
|
||||
if (!empty($extraQuery)) {
|
||||
parse_str($extraQuery, $parsed);
|
||||
|
||||
if (!empty($parsed['dlid']) && preg_match('/^MOKO-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/', $parsed['dlid'])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->getApplication()->enqueueMessage(
|
||||
'<strong>MokoJoomHero — Download Key Required</strong> — '
|
||||
. 'No download key is configured. Updates may not be available until a valid key is entered. '
|
||||
. 'Go to <a href="index.php?option=com_installer&view=updatesites">System → Update Sites</a> '
|
||||
. 'and enter your download key (<code>MOKO-XXXX-XXXX-XXXX-XXXX</code>) for the MokoJoomHero update site.',
|
||||
'warning'
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->getApplication()->getLogger()->warning(
|
||||
'MokoJoomHero license check failed: ' . $e->getMessage(),
|
||||
['exception' => $e]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1 +0,0 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* @package MokoJoomHero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
-->
|
||||
<extension type="package" method="upgrade">
|
||||
<name>Package - MokoJoomHero</name>
|
||||
<packagename>mokojoomhero</packagename>
|
||||
<version>01.12.00</version>
|
||||
<creationDate>2026-06-02</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<description>Random hero image slideshow or background video with content overlay. Includes the hero module and system plugin. By Moko Consulting.</description>
|
||||
|
||||
<scriptfile>pkg_script.php</scriptfile>
|
||||
|
||||
<files folder="packages">
|
||||
<file type="module" id="mod_mokojoomhero" client="site">mod_mokojoomhero.zip</file>
|
||||
<file type="plugin" id="mokojoomhero" group="system">plg_system_mokojoomhero.zip</file>
|
||||
</files>
|
||||
|
||||
<updateservers>
|
||||
<server type="extension" name="MokoJoomHero Updates">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero/updates.xml</server>
|
||||
</updateservers>
|
||||
</extension>
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package MokoJoomHero
|
||||
* @author Moko Consulting <hello@mokoconsulting.tech>
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Installer\InstallerAdapter;
|
||||
|
||||
class Pkg_MokoJoomHeroInstallerScript
|
||||
{
|
||||
/**
|
||||
* Called after install/update — only enables the system plugin on fresh install.
|
||||
*
|
||||
* @param string $type Action type
|
||||
* @param InstallerAdapter $parent Installer adapter
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function postflight(string $type, InstallerAdapter $parent): void
|
||||
{
|
||||
if ($type === 'install') {
|
||||
try {
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Enable the system plugin automatically on fresh install
|
||||
$query = $db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('enabled') . ' = 1')
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
|
||||
->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokojoomhero'));
|
||||
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
if ($db->getAffectedRows() === 0) {
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoJoomHero: The system plugin could not be auto-enabled. '
|
||||
. 'Please enable it manually in Extensions → Plugins.',
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoJoomHero: Failed to auto-enable system plugin: ' . $e->getMessage()
|
||||
. ' — Please enable it manually in Extensions → Plugins.',
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user