Files
MokoJoomHero/src/mod_mokojoomhero.php
T
Jonathan Miller d738d75fad
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Universal: Auto Version Bump / Version Bump (push) Has been cancelled
Update Server / Update Server (push) Has been cancelled
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
feat: add WYSIWYG content editor with card display on hero
- Add heroContent param with Joomla editor field for rich HTML input
- Add showCard toggle to wrap content in a styled card (white bg, shadow, rounded)
- Card CSS: semi-transparent white, 8px radius, centered, max 700px
- Remove old $module->content fallback — content now comes from params
- Language strings for en-GB and en-US (both .ini and .sys.ini)

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 22:55:54 -05:00

90 lines
3.0 KiB
PHP

<?php
/**
* @package Joomla.Site
* @subpackage mod_mokojoomhero
*
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GPL-3.0-or-later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Uri\Uri;
/** @var \Joomla\CMS\Application\SiteApplication $app */
/** @var \stdClass $module */
/** @var \Joomla\Registry\Registry $params */
// Register and load module assets via Web Asset Manager
$wa = $app->getDocument()->getWebAssetManager();
$wa->getRegistry()->addExtensionRegistryFile('mod_mokojoomhero');
$wa->usePreset('mod_mokojoomhero');
// Module parameters
$heroMode = $params->get('heroMode', 'images');
$imageFolder = $params->get('imageFolder', 'images/heroes');
$imageCount = (int) $params->get('imageCount', 5);
$slideInterval = (int) $params->get('slideInterval', 5000);
$videoFile = $params->get('videoFile', '');
$heroHeight = $params->get('heroHeight', '60vh');
$overlayColor = $params->get('overlayColor', '#000000');
$overlayOpacity = (float) $params->get('overlayOpacity', 0.5);
$textAlign = $params->get('textAlign', 'center');
$textColor = $params->get('textColor', '#ffffff');
$heroContent = $params->get('heroContent', '');
$showCard = (bool) $params->get('showCard', 1);
// Collect hero images
$heroImages = [];
if ($heroMode === 'images') {
$folderPath = JPATH_ROOT . '/' . ltrim($imageFolder, '/');
if (is_dir($folderPath)) {
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'svg'];
$all = [];
foreach (new DirectoryIterator($folderPath) as $file) {
if ($file->isFile() && in_array(strtolower($file->getExtension()), $allowed, true)) {
$all[] = $file->getFilename();
}
}
if ($all) {
shuffle($all);
$picked = array_slice($all, 0, min($imageCount, 5));
foreach ($picked as $filename) {
$heroImages[] = Uri::root() . $imageFolder . '/' . $filename;
}
}
}
}
// Build video URL — smartly detect YouTube, Vimeo, or local/direct file
$videoUrl = '';
$youtubeId = '';
$vimeoId = '';
if ($heroMode === 'video' && $videoFile) {
// YouTube: watch, embed, shorts, youtu.be, with optional timestamps/params
if (preg_match('/(?:youtube\.com\/(?:watch\?.*v=|embed\/|shorts\/|v\/)|youtu\.be\/)([\w-]{11})/', $videoFile, $m)) {
$youtubeId = $m[1];
// Vimeo: vimeo.com/123456 or player.vimeo.com/video/123456
} elseif (preg_match('/vimeo\.com\/(?:video\/)?(\d+)/', $videoFile, $m)) {
$vimeoId = $m[1];
} else {
// Direct URL or local file path
$videoUrl = (strpos($videoFile, '://') !== false)
? $videoFile
: Uri::root() . ltrim($videoFile, '/');
}
}
// Module content from the editor (overlay text)
$content = $module->content ?? '';
require ModuleHelper::getLayoutPath('mod_mokojoomhero', $params->get('layout', 'default'));