Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 065b25fc88 | |||
| 4ca69e5af3 | |||
| fd359ae7f7 | |||
| 4c6d9396f8 | |||
| 1513d6d51a | |||
| 3083aa6e0e |
@@ -9,7 +9,7 @@
|
||||
<display-name>Template - MokoOnyx</display-name>
|
||||
<org>MokoConsulting</org>
|
||||
<description>MokoOnyx - Joomla site template (successor to MokoCassiopeia)</description>
|
||||
<version>02.20.00</version>
|
||||
<version>02.18.03</version>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
<governance>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Automation
|
||||
# VERSION: 02.20.00
|
||||
# VERSION: 02.18.03
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
|
||||
name: "Universal: Issue Branch"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||
# PATH: /templates/workflows/joomla/repo_health.yml.template
|
||||
# VERSION: 09.23.00
|
||||
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
|
||||
# BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts.
|
||||
# ============================================================================
|
||||
|
||||
name: "Generic: Repo Health"
|
||||
@@ -24,12 +24,13 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
profile:
|
||||
description: 'Validation profile: all, scripts, or repo'
|
||||
description: 'Validation profile: all, release, scripts, or repo'
|
||||
required: true
|
||||
default: all
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- release
|
||||
- scripts
|
||||
- repo
|
||||
pull_request:
|
||||
@@ -39,6 +40,10 @@ permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Release policy - Repository Variables Only
|
||||
RELEASE_REQUIRED_REPO_VARS: RS_FTP_PATH_SUFFIX
|
||||
RELEASE_OPTIONAL_REPO_VARS: DEV_FTP_SUFFIX
|
||||
|
||||
# Scripts governance policy
|
||||
SCRIPTS_REQUIRED_DIRS:
|
||||
SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate
|
||||
@@ -133,6 +138,101 @@ jobs:
|
||||
printf '%s\n' 'ERROR: Access denied. Admin permission required.' >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 1
|
||||
|
||||
release_config:
|
||||
name: Release configuration
|
||||
needs: access_check
|
||||
if: ${{ needs.access_check.outputs.allowed == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Guardrails release vars
|
||||
env:
|
||||
PROFILE_RAW: ${{ github.event.inputs.profile }}
|
||||
RS_FTP_PATH_SUFFIX: ${{ vars.RS_FTP_PATH_SUFFIX }}
|
||||
DEV_FTP_SUFFIX: ${{ vars.DEV_FTP_SUFFIX }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
profile="${PROFILE_RAW:-all}"
|
||||
case "${profile}" in
|
||||
all|release|scripts|repo) ;;
|
||||
*)
|
||||
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "${profile}" = 'scripts' ] || [ "${profile}" = 'repo' ]; then
|
||||
{
|
||||
printf '%s\n' '### Release configuration (Repository Variables)'
|
||||
printf '%s\n' "Profile: ${profile}"
|
||||
printf '%s\n' 'Status: SKIPPED'
|
||||
printf '%s\n' 'Reason: profile excludes release validation'
|
||||
printf '\n'
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
IFS=',' read -r -a required <<< "${RELEASE_REQUIRED_REPO_VARS}"
|
||||
IFS=',' read -r -a optional <<< "${RELEASE_OPTIONAL_REPO_VARS}"
|
||||
|
||||
missing=()
|
||||
missing_optional=()
|
||||
|
||||
for k in "${required[@]}"; do
|
||||
v="${!k:-}"
|
||||
[ -z "${v}" ] && missing+=("${k}")
|
||||
done
|
||||
|
||||
for k in "${optional[@]}"; do
|
||||
v="${!k:-}"
|
||||
[ -z "${v}" ] && missing_optional+=("${k}")
|
||||
done
|
||||
|
||||
{
|
||||
printf '%s\n' '### Release configuration (Repository Variables)'
|
||||
printf '%s\n' "Profile: ${profile}"
|
||||
printf '%s\n' '| Variable | Status |'
|
||||
printf '%s\n' '|---|---|'
|
||||
printf '%s\n' "| RS_FTP_PATH_SUFFIX | ${RS_FTP_PATH_SUFFIX:-NOT SET} |"
|
||||
printf '%s\n' "| DEV_FTP_SUFFIX | ${DEV_FTP_SUFFIX:-NOT SET} |"
|
||||
printf '\n'
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
|
||||
if [ "${#missing_optional[@]}" -gt 0 ]; then
|
||||
{
|
||||
printf '%s\n' '### Missing optional repository variables'
|
||||
for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done
|
||||
printf '\n'
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
fi
|
||||
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
{
|
||||
printf '%s\n' '### Missing required repository variables'
|
||||
for m in "${missing[@]}"; do printf '%s\n' "- ${m}"; done
|
||||
printf '%s\n' 'ERROR: Guardrails failed. Missing required repository variables.'
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{
|
||||
printf '%s\n' '### Repository variables validation result'
|
||||
printf '%s\n' 'Status: OK'
|
||||
printf '%s\n' 'All required repository variables present.'
|
||||
printf '%s\n' ''
|
||||
printf '%s\n' '**Note**: Organization secrets (RS_FTP_HOST, RS_FTP_USER, etc.) are validated at deployment time, not in repository health checks.'
|
||||
printf '\n'
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
|
||||
scripts_governance:
|
||||
name: Scripts governance
|
||||
needs: access_check
|
||||
@@ -156,14 +256,14 @@ jobs:
|
||||
|
||||
profile="${PROFILE_RAW:-all}"
|
||||
case "${profile}" in
|
||||
all|scripts|repo) ;;
|
||||
all|release|scripts|repo) ;;
|
||||
*)
|
||||
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "${profile}" = 'repo' ]; then
|
||||
if [ "${profile}" = 'release' ] || [ "${profile}" = 'repo' ]; then
|
||||
{
|
||||
printf '%s\n' '### Scripts governance'
|
||||
printf '%s\n' "Profile: ${profile}"
|
||||
@@ -270,14 +370,14 @@ jobs:
|
||||
|
||||
profile="${PROFILE_RAW:-all}"
|
||||
case "${profile}" in
|
||||
all|scripts|repo) ;;
|
||||
all|release|scripts|repo) ;;
|
||||
*)
|
||||
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "${profile}" = 'scripts' ]; then
|
||||
if [ "${profile}" = 'release' ] || [ "${profile}" = 'scripts' ]; then
|
||||
{
|
||||
printf '%s\n' '### Repository health'
|
||||
printf '%s\n' "Profile: ${profile}"
|
||||
@@ -604,7 +704,7 @@ jobs:
|
||||
printf '%s\n' '| Domain | Status | Notes |'
|
||||
printf '%s\n' '|---|---|---|'
|
||||
printf '%s\n' '| Access control | OK | Admin-only execution gate |'
|
||||
printf '%s\n' '| Release policy | N/A | Releases handled by MokoGitea |'
|
||||
printf '%s\n' '| Release variables | OK | Repository variables validation |'
|
||||
printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |'
|
||||
printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |'
|
||||
printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |'
|
||||
@@ -673,10 +773,11 @@ jobs:
|
||||
report-issues:
|
||||
name: "Report Issues"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [access_check, scripts_governance, repo_health]
|
||||
needs: [access_check, release_config, scripts_governance, repo_health]
|
||||
if: >-
|
||||
always() &&
|
||||
(needs.scripts_governance.result == 'failure' ||
|
||||
(needs.release_config.result == 'failure' ||
|
||||
needs.scripts_governance.result == 'failure' ||
|
||||
needs.repo_health.result == 'failure')
|
||||
|
||||
steps:
|
||||
@@ -702,6 +803,10 @@ jobs:
|
||||
fi
|
||||
}
|
||||
|
||||
report_gate "Release Configuration" \
|
||||
"${{ needs.release_config.result }}" \
|
||||
"Required repository variables are missing (RS_FTP_PATH_SUFFIX). Check repository settings."
|
||||
|
||||
report_gate "Scripts Governance" \
|
||||
"${{ needs.scripts_governance.result }}" \
|
||||
"Scripts directory policy violations detected. Review required and allowed directories."
|
||||
@@ -709,3 +814,4 @@ jobs:
|
||||
report_gate "Repository Health" \
|
||||
"${{ needs.repo_health.result }}" \
|
||||
"Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
|
||||
|
||||
|
||||
+28
-6
@@ -8,19 +8,41 @@
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoOnyx.Documentation
|
||||
PATH: ./CHANGELOG.md
|
||||
VERSION: 02.20.00
|
||||
VERSION: 02.18.03
|
||||
BRIEF: Changelog file documenting version history of MokoOnyx
|
||||
-->
|
||||
|
||||
# Changelog — MokoOnyx (VERSION: 02.20.00)
|
||||
# Changelog — MokoOnyx (VERSION: 02.18.03)
|
||||
## [Unreleased]
|
||||
|
||||
## [02.20.00] --- 2026-06-04
|
||||
|
||||
## [02.19.00] --- 2026-06-04
|
||||
|
||||
## [02.18.00] --- 2026-06-02
|
||||
|
||||
## [02.17.00] --- 2026-06-02
|
||||
|
||||
## [02.15.00] --- 2026-05-30
|
||||
## [02.14.00] --- 2026-05-30
|
||||
|
||||
## [02.13.00] --- 2026-05-30
|
||||
|
||||
### Added
|
||||
- Hero image (`hero.jpg`) to template images
|
||||
- `.fa-solid`, `.fa-regular`, `.fa-brands`, `.fa-light` icon margin spacing
|
||||
- `.blog-item .item-image` fixed 250px height with object-fit cover
|
||||
- Hide header on home page option (`hideHeaderHome` template param)
|
||||
- Hide main menu on home page option (`hideMenuHome` template param)
|
||||
- Three distinct menu overrides: mainmenu (collapsible), horizontal (always visible), default (vertical)
|
||||
- `<php_minimum>8.1.0</php_minimum>` to templateDetails.xml
|
||||
- `<changelogurl>` support in updates.xml
|
||||
- CONTRIBUTING.md with universal workflow and version policy
|
||||
|
||||
### Changed
|
||||
- Release pipeline rework: independent update streams, CLI-driven workflows
|
||||
- Version bumps only trigger on `src/` changes (not docs/config)
|
||||
- Branch protection: CI bot only for push, force push disabled
|
||||
- Auto-bump supports dev, rc, feature/*, patch/* branches
|
||||
|
||||
### Fixed
|
||||
- Joomla update loop caused by version mismatch between ZIP and updates.xml
|
||||
- Duplicate hamburger menu on mobile
|
||||
- Stacked version suffixes (-dev-dev-dev)
|
||||
- Template name doubling (Template - Template - MokoOnyx)
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
INGROUP: MokoOnyx.Governance
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
FILE: SECURITY.md
|
||||
VERSION: 02.20.00
|
||||
VERSION: 02.18.03
|
||||
BRIEF: Security policy and vulnerability reporting process for MokoOnyx.
|
||||
PATH: /SECURITY.md
|
||||
NOTE: This policy is process oriented and does not replace secure engineering practices.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/layouts/joomla/module/card.php
|
||||
* VERSION: 02.20.00
|
||||
* VERSION: 02.18.03
|
||||
* BRIEF: Custom card module chrome — renders module titles for all modules
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* INGROUP: MokoOnyx.Layouts
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /src/html/layouts/mokoonyx/article-metadata.php
|
||||
* VERSION: 02.20.00
|
||||
* VERSION: 02.18.03
|
||||
* BRIEF: Article metadata footer layout -- renders jcfields grouped by field group
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* INGROUP: MokoOnyx.Accessibility
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: ./media/css/a11y-high-contrast.css
|
||||
* VERSION: 02.20.00
|
||||
* VERSION: 02.18.03
|
||||
* BRIEF: High-contrast stylesheet for accessibility toolbar
|
||||
*/
|
||||
|
||||
|
||||
+140
-71
@@ -65,6 +65,8 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface
|
||||
{
|
||||
$this->logMessage('MokoOnyx template updated.');
|
||||
|
||||
$this->migrateUpdateServer();
|
||||
|
||||
$synced = $this->syncCustomVariables($parent);
|
||||
if ($synced > 0) {
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
@@ -94,7 +96,6 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface
|
||||
$this->clearFaviconStamp();
|
||||
$this->cleanMediaFolder();
|
||||
$this->removeDeletedFiles();
|
||||
$this->removeDuplicateExtensions();
|
||||
$this->lockExtension();
|
||||
}
|
||||
|
||||
@@ -485,93 +486,161 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
// LICENSE & UPDATE SERVER MIGRATION
|
||||
// ====================================================================
|
||||
|
||||
/**
|
||||
* Remove duplicate MokoOnyx extension entries from #__extensions.
|
||||
* New update server URL (MokoGitea license system).
|
||||
*
|
||||
* Re-installs or migrations can leave ghost rows. We keep the one
|
||||
* that is locked (the active template) and delete any extras.
|
||||
* Also removes stale MokoCassiopeia entries if present.
|
||||
* TODO: Replace with the actual licensed update server endpoint once
|
||||
* the MokoGitea license system is configured. The URL should
|
||||
* accept a `dlid` query parameter for download-key auth.
|
||||
*
|
||||
* Example: https://updates.mokoconsulting.tech/joomla/mokoonyx/updates.xml
|
||||
*/
|
||||
private function removeDuplicateExtensions(): void
|
||||
private const NEW_UPDATE_URL = ''; // TODO: set final URL
|
||||
|
||||
/**
|
||||
* Old update server URLs that should be removed during migration.
|
||||
*/
|
||||
private const OLD_UPDATE_URLS = [
|
||||
'https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml',
|
||||
];
|
||||
|
||||
/**
|
||||
* Migrate the update server from the old raw-branch URL to the new
|
||||
* MokoGitea license system.
|
||||
*
|
||||
* 1. Find existing update site entries for this template
|
||||
* 2. Remove old entries pointing to the raw-branch URL
|
||||
* 3. (When NEW_UPDATE_URL is set) create the new update site entry
|
||||
* 4. Warn the admin if no download key is configured
|
||||
*
|
||||
* Safe to run multiple times — skips if already migrated.
|
||||
*/
|
||||
private function migrateUpdateServer(): void
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Find all MokoOnyx template entries
|
||||
$rows = $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select(['extension_id', 'locked'])
|
||||
->from('#__extensions')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote(self::NEW_NAME))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
->order('locked DESC, extension_id ASC')
|
||||
)->loadObjectList();
|
||||
|
||||
if (count($rows) > 1) {
|
||||
$keep = (int) $rows[0]->extension_id;
|
||||
$removed = 0;
|
||||
|
||||
for ($i = 1; $i < count($rows); $i++) {
|
||||
$staleId = (int) $rows[$i]->extension_id;
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__update_sites_extensions')
|
||||
->where('extension_id = ' . $staleId)
|
||||
)->execute();
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__extensions')
|
||||
->where('extension_id = ' . $staleId)
|
||||
)->execute();
|
||||
|
||||
$removed++;
|
||||
}
|
||||
|
||||
if ($removed > 0) {
|
||||
$this->logMessage("Removed {$removed} duplicate MokoOnyx extension(s). Kept ID {$keep}.");
|
||||
}
|
||||
if (empty(self::NEW_UPDATE_URL)) {
|
||||
// Migration not yet active — URL not configured
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove stale MokoCassiopeia if not set as default
|
||||
$oldExt = (int) $db->setQuery(
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Find the extension ID for this template
|
||||
$extId = (int) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('extension_id')
|
||||
->from('#__extensions')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote(self::OLD_NAME))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote(self::NEW_NAME))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
)->loadResult();
|
||||
|
||||
if ($oldExt) {
|
||||
$isDefault = (int) $db->setQuery(
|
||||
if (!$extId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already migrated (new URL exists)
|
||||
$alreadyMigrated = (int) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__update_sites AS us')
|
||||
->join('INNER', '#__update_sites_extensions AS use ON us.update_site_id = use.update_site_id')
|
||||
->where('use.extension_id = ' . $extId)
|
||||
->where($db->quoteName('us.location') . ' = ' . $db->quote(self::NEW_UPDATE_URL))
|
||||
)->loadResult();
|
||||
|
||||
if ($alreadyMigrated) {
|
||||
$this->checkDownloadKey($extId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove old update site entries
|
||||
$oldSiteIds = $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('us.update_site_id')
|
||||
->from('#__update_sites AS us')
|
||||
->join('INNER', '#__update_sites_extensions AS use ON us.update_site_id = use.update_site_id')
|
||||
->where('use.extension_id = ' . $extId)
|
||||
->whereIn($db->quoteName('us.location'), array_map([$db, 'quote'], self::OLD_UPDATE_URLS), true)
|
||||
)->loadColumn();
|
||||
|
||||
if (!empty($oldSiteIds)) {
|
||||
$ids = implode(',', array_map('intval', $oldSiteIds));
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from('#__template_styles')
|
||||
->where($db->quoteName('template') . ' = ' . $db->quote(self::OLD_NAME))
|
||||
->where($db->quoteName('home') . ' = 1')
|
||||
)->loadResult();
|
||||
->delete('#__update_sites_extensions')
|
||||
->whereIn('update_site_id', $oldSiteIds)
|
||||
)->execute();
|
||||
|
||||
if ($isDefault === 0) {
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__update_sites_extensions')
|
||||
->where('extension_id = ' . $oldExt)
|
||||
)->execute();
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__update_sites')
|
||||
->whereIn('update_site_id', $oldSiteIds)
|
||||
)->execute();
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__extensions')
|
||||
->where('extension_id = ' . $oldExt)
|
||||
)->execute();
|
||||
$this->logMessage('Removed ' . count($oldSiteIds) . ' old update site(s).');
|
||||
}
|
||||
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete('#__template_styles')
|
||||
->where($db->quoteName('template') . ' = ' . $db->quote(self::OLD_NAME))
|
||||
)->execute();
|
||||
// Create new update site entry
|
||||
$newSite = (object) [
|
||||
'name' => 'MokoOnyx Updates (Licensed)',
|
||||
'type' => 'extension',
|
||||
'location' => self::NEW_UPDATE_URL,
|
||||
'enabled' => 1,
|
||||
'last_check_timestamp' => 0,
|
||||
'extra_query' => '',
|
||||
];
|
||||
|
||||
$this->logMessage('Removed stale MokoCassiopeia extension and styles.');
|
||||
}
|
||||
$db->insertObject('#__update_sites', $newSite, 'update_site_id');
|
||||
$newSiteId = (int) $newSite->update_site_id;
|
||||
|
||||
if ($newSiteId) {
|
||||
$link = (object) [
|
||||
'update_site_id' => $newSiteId,
|
||||
'extension_id' => $extId,
|
||||
];
|
||||
$db->insertObject('#__update_sites_extensions', $link);
|
||||
$this->logMessage('Created new licensed update site (ID: ' . $newSiteId . ').');
|
||||
}
|
||||
|
||||
$this->checkDownloadKey($extId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a download key is configured for this extension's
|
||||
* update site and warn the admin if not.
|
||||
*/
|
||||
private function checkDownloadKey(int $extId): void
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
$row = $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select(['us.update_site_id', 'us.extra_query'])
|
||||
->from('#__update_sites AS us')
|
||||
->join('INNER', '#__update_sites_extensions AS use ON us.update_site_id = use.update_site_id')
|
||||
->where('use.extension_id = ' . $extId)
|
||||
->where($db->quoteName('us.location') . ' = ' . $db->quote(self::NEW_UPDATE_URL))
|
||||
)->loadObject();
|
||||
|
||||
if (!$row) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Joomla stores the download key in extra_query as "dlid=XXXXX"
|
||||
if (empty($row->extra_query) || strpos($row->extra_query, 'dlid=') === false) {
|
||||
$editUrl = 'index.php?option=com_installer&view=updatesites&task=updatesite.edit&update_site_id='
|
||||
. (int) $row->update_site_id;
|
||||
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'<strong>MokoOnyx — Download key required.</strong><br>'
|
||||
. 'A download key is needed to receive updates. '
|
||||
. '<a href="' . $editUrl . '">Enter your download key here</a>.',
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
<extension type="template" client="site" method="upgrade">
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="MokoOnyx Update Server (MokoGitea)">
|
||||
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/updates.xml
|
||||
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
<name>mokoonyx</name>
|
||||
<version>02.20.00</version>
|
||||
<version>02.18.03-dev</version>
|
||||
<scriptfile>script.php</scriptfile>
|
||||
<creationDate>2026-05-16</creationDate>
|
||||
<author>Jonathan Miller || Moko Consulting</author>
|
||||
|
||||
+6
-26
@@ -1,48 +1,28 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
VERSION: 02.20.00-dev
|
||||
VERSION: 02.20.00
|
||||
-->
|
||||
|
||||
<updates>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx development build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<client>site</client>
|
||||
<version>02.19.02-dev</version>
|
||||
<creationDate>2026-06-04</creationDate>
|
||||
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/development</infourl>
|
||||
<downloads>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.19.02-dev.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>5811cc175564744865053f5a2cf259e66016c4e41f2d87571d19b1dd5f7fd8ba</sha256>
|
||||
<tags><tag>dev</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx stable build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<client>site</client>
|
||||
<version>02.19.00</version>
|
||||
<version>02.20.00</version>
|
||||
<creationDate>2026-06-04</creationDate>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.19.00.zip</downloadurl>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.20.00.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>1b4907b450be64d1d23ea0da4314e542e6abf2c9e6e2085ad4b2e49079bd1d83</sha256>
|
||||
<sha256>6b0397fce0e1f9e15f3318a200ad4679a0777940c6cfa3a703b875ca14f9979a</sha256>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
</updates>
|
||||
|
||||
Reference in New Issue
Block a user