diff --git a/.mokogitea/CLAUDE.md b/.mokogitea/CLAUDE.md new file mode 100644 index 0000000..1384552 --- /dev/null +++ b/.mokogitea/CLAUDE.md @@ -0,0 +1,63 @@ +# MokoOnyx + +Joomla site template — successor to MokoCassiopeia. Base template for all WaaS client deployments. + +## Quick Reference + +| Field | Value | +|---|---| +| **Element** | `tpl_mokoonyx` | +| **Type** | Joomla site template | +| **Language** | PHP 8.1+ / CSS / JS | +| **Branch** | develop on `dev`, merge to `main` (protected) | +| **Wiki** | [MokoOnyx Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/wiki) | + +## Commands + +```bash +make build # Build template ZIP +make lint # Run linters +make validate # Validate structure +make release # Full release pipeline +make minify # Minify CSS/JS assets +make clean # Clean build artifacts +composer install # Install PHP dependencies +``` + +## Architecture + +Joomla **site template** — the base layer that client theme packages override: + +- `src/templateDetails.xml` — template manifest +- `src/index.php` — main template entry point +- `src/error.php` — error page +- `src/offline.php` — maintenance page +- `src/component.php` — print/component-only layout +- `src/html/` — template overrides for core components +- `src/media/css/` — base stylesheets +- `src/media/js/` — base scripts +- `src/media/images/` — template images +- `src/language/` — translations + +### Client Theme Packages + +Client repos (`client-clarksvillefurs`, `client-optainfunding`, etc.) install `type="file"` packages that overlay client-specific CSS, images, and JS into the MokoOnyx media directory. MokoOnyx provides the structure; client themes customize the appearance. + +### Minification + +`MokoMinifyHelper` handles runtime CSS/JS minification in Joomla. Build-time minification via `make minify`. Never commit `*.min.css`/`*.min.js` — they're generated. + +## Rules + +- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, `*.min.css`/`*.min.js` +- **Attribution**: `Authored-by: Moko Consulting` +- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) +- **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper) +- **Wiki**: documentation lives in the Gitea wiki, not `docs/` files +- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) + +## Coding Standards + +- PHP 8.1+ minimum +- SPDX license headers on all PHP files +- `defined('_JEXEC') or die;` on all PHP files diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml index e134379..d7e107c 100644 --- a/.mokogitea/manifest.xml +++ b/.mokogitea/manifest.xml @@ -9,7 +9,7 @@ Template - MokoOnyx MokoConsulting MokoOnyx - Joomla site template (successor to MokoCassiopeia) - 02.20.00 + 02.19.07 GNU General Public License v3 diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index 44a2d64..ca40435 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -17,7 +17,7 @@ # | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. | # | | # | Platform-specific: | -# | joomla: XML manifest, updates.xml, type-prefixed packages | +# | joomla: XML manifest, type-prefixed packages | # | dolibarr: mod*.class.php, update.txt, dev version reset | # | generic: README-only, no update stream | # | | @@ -71,20 +71,25 @@ jobs: MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting run: | - if ! command -v composer &> /dev/null; then - sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1 + if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then + echo Using pre-installed /opt/moko-platform + echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV + else + echo Falling back to fresh clone + if ! command -v composer > /dev/null 2>&1; then + sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 + fi + rm -rf /tmp/moko-platform-api + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git + git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api + cd /tmp/moko-platform-api + composer install --no-dev --no-interaction --quiet + echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV fi - # Always fetch latest CLI tools — never use stale cache from previous runs - rm -rf /tmp/moko-platform-api - git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \ - /tmp/moko-platform-api - cd /tmp/moko-platform-api - composer install --no-dev --no-interaction --quiet - name: Rename branch to rc run: | - php /tmp/moko-platform-api/cli/branch_rename.php \ + php ${MOKO_CLI}/branch_rename.php \ --from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \ --token "${{ secrets.MOKOGITEA_TOKEN }}" \ --api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \ @@ -100,16 +105,15 @@ jobs: - name: Publish RC release run: | - php /tmp/moko-platform-api/cli/release_publish.php \ + php ${MOKO_CLI}/release_publish.php \ --path . --stability rc --bump minor --branch rc \ - --token "${{ secrets.MOKOGITEA_TOKEN }}" \ - --skip-update-stream + --token "${{ secrets.MOKOGITEA_TOKEN }}" - name: Summary if: always() run: | echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY - echo "Branch renamed to rc, minor bump, RC release built (updates.xml managed by Gitea Pages)" >> $GITHUB_STEP_SUMMARY + echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY # ── Merged PR → Build & Release (or promote RC to stable) ──────────────────── release: @@ -151,25 +155,60 @@ jobs: MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}' run: | - # Ensure PHP + Composer are available - if ! command -v composer &> /dev/null; then - sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1 + if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then + echo Using pre-installed /opt/moko-platform + echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV + else + echo Falling back to fresh clone + if ! command -v composer > /dev/null 2>&1; then + sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 + fi + rm -rf /tmp/moko-platform-api + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git + git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api + cd /tmp/moko-platform-api + composer install --no-dev --no-interaction --quiet + echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV fi - # Always fetch latest CLI tools — never use stale cache from previous runs - rm -rf /tmp/moko-platform-api - git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \ - /tmp/moko-platform-api - cd /tmp/moko-platform-api - composer install --no-dev --no-interaction --quiet - - name: "Publish stable release" run: | - php /tmp/moko-platform-api/cli/release_publish.php \ + php ${MOKO_CLI}/release_publish.php \ --path . --stability stable --bump minor --branch main \ - --token "${{ secrets.MOKOGITEA_TOKEN }}" \ - --skip-update-stream + --token "${{ secrets.MOKOGITEA_TOKEN }}" + + - name: Update release notes from CHANGELOG.md + run: | + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + + # Extract [Unreleased] section from changelog + if [ -f "CHANGELOG.md" ]; then + NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md) + [ -z "$NOTES" ] && NOTES="Stable release" + else + NOTES="Stable release" + fi + + # Update release body via API + RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ + "${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true) + + if [ -n "$RELEASE_ID" ]; then + python3 -c " + import json, urllib.request + body = open('/dev/stdin').read() + payload = json.dumps({'body': body}).encode() + req = urllib.request.Request( + '${API_BASE}/releases/${RELEASE_ID}', + data=payload, method='PATCH', + headers={ + 'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}', + 'Content-Type': 'application/json' + }) + urllib.request.urlopen(req) + " <<< "$NOTES" + echo "Release notes updated from CHANGELOG.md" + fi # -- STEP 9: Mirror to GitHub (stable only) -------------------------------- - name: "Step 9: Mirror release to GitHub" @@ -182,7 +221,7 @@ jobs: RELEASE_TAG="${{ steps.version.outputs.release_tag }}" GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}" API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - php /tmp/moko-platform-api/cli/release_mirror.php \ + php ${MOKO_CLI}/release_mirror.php \ --version "$VERSION" --tag "$RELEASE_TAG" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ --gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \ @@ -256,7 +295,7 @@ jobs: continue-on-error: true run: | API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - php /tmp/moko-platform-api/cli/version_reset_dev.php \ + php ${MOKO_CLI}/version_reset_dev.php \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \ --branch dev --path . 2>&1 || true diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 5e03998..3a44f6a 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: moko-platform.Automation -# VERSION: 02.20.00 +# VERSION: 02.19.07 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index 780150d..9615a4e 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -1,259 +1,243 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Gitea.Workflow -# INGROUP: moko-platform.Release -# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform -# PATH: /templates/workflows/universal/pre-release.yml.template -# VERSION: 05.01.00 -# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch - -name: "Universal: Pre-Release" - -on: - pull_request: - types: [closed] - branches: - - dev - pull_request_target: - types: [synchronize, opened, reopened] - branches: - - main - workflow_dispatch: - inputs: - stability: - description: 'Pre-release channel' - required: true - type: choice - options: - - development - - alpha - - beta - - release-candidate - -permissions: - contents: write - -env: - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} - GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} - -jobs: - build: - name: "Build Pre-Release (${{ inputs.stability || 'development' }})" - runs-on: release - if: >- - github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev') || - (github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == 'main') - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.MOKOGITEA_TOKEN }} - ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }} - - - name: Setup moko-platform tools - env: - MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting - run: | - if ! command -v composer &> /dev/null; then - sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1 - fi - # Always fetch latest CLI tools — never use stale cache from previous runs - rm -rf /tmp/moko-platform-api - git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \ - /tmp/moko-platform-api - cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet - echo "MOKO_CLI=/tmp/moko-platform-api/cli" >> "$GITHUB_ENV" - - - name: Detect platform - id: platform - run: | - php ${MOKO_CLI}/manifest_read.php --path . --github-output - - - name: Resolve metadata and bump version - id: meta - run: | - # Auto-detect stability: RC for PRs targeting main, else use input or default to development - if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then - STABILITY="release-candidate" - else - STABILITY="${{ inputs.stability || 'development' }}" - fi - - case "$STABILITY" in - development) SUFFIX="-dev"; TAG="development" ;; - alpha) SUFFIX="-alpha"; TAG="alpha" ;; - beta) SUFFIX="-beta"; TAG="beta" ;; - release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;; - esac - - # Read current version (bump already handled by push workflow) - VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null) - [ -z "$VERSION" ] && VERSION="00.00.01" - - # Strip any existing suffix from version before applying stability - VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//') - - php ${MOKO_CLI}/version_set_platform.php \ - --path . --version "$VERSION" --branch "${{ github.ref_name }}" --stability "$STABILITY" 2>/dev/null || true - - # Verify version consistency across all files - php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true - - # Update VERSION variable with suffix - if [ -n "$SUFFIX" ]; then - VERSION="${VERSION}${SUFFIX}" - fi - - # Commit version bump - git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" - git config --local user.name "gitea-actions[bot]" - git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" - git add -A - git diff --cached --quiet || { - git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]" - git push origin HEAD 2>&1 - } - - # Auto-detect element via manifest_element.php - php ${MOKO_CLI}/manifest_element.php \ - --path . --version "$VERSION" --stability "$STABILITY" \ - --repo "${GITEA_REPO}" --github-output - - # Read back element outputs - EXT_ELEMENT=$(grep '^ext_element=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2) - ZIP_NAME=$(grep '^zip_name=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2) - [ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') - [ -z "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip" - - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT" - echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT" - echo "tag=${TAG}" >> "$GITHUB_OUTPUT" - echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT" - echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT" - - echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ===" - - - name: Create release - id: release - run: | - TAG="${{ steps.meta.outputs.tag }}" - VERSION="${{ steps.meta.outputs.version }}" - API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - php ${MOKO_CLI}/release_create.php \ - --path . --version "$VERSION" --tag "$TAG" \ - --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ - --repo "${GITEA_REPO}" --branch dev --prerelease - - - name: Ensure prerelease flag - run: | - TAG="${{ steps.meta.outputs.tag }}" - API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - # Get release ID by tag and force prerelease=true - RELEASE_ID=$(curl -s "${API_BASE}/releases/tags/${TAG}" \ - -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" | jq -r '.id // empty') - if [ -n "$RELEASE_ID" ]; then - curl -s -X PATCH "${API_BASE}/releases/${RELEASE_ID}" \ - -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ - -H "Content-Type: application/json" \ - -d '{"prerelease": true}' - echo "Marked release ${TAG} (id=${RELEASE_ID}) as prerelease" - fi - - - name: Build package and upload - id: package - run: | - VERSION="${{ steps.meta.outputs.version }}" - TAG="${{ steps.meta.outputs.tag }}" - API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - php ${MOKO_CLI}/release_package.php \ - --path . --version "$VERSION" --tag "$TAG" \ - --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ - --repo "${GITEA_REPO}" --output /tmp || true - - - name: Update updates.xml - if: steps.platform.outputs.platform == 'joomla' - run: | - VERSION="${{ steps.meta.outputs.version }}" - STABILITY="${{ steps.meta.outputs.stability }}" - SHA256="${{ steps.package.outputs.sha256_zip }}" - - if [ ! -f "updates.xml" ]; then - echo "No updates.xml -- skipping" - exit 0 - fi - - SHA_FLAG="" - [ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}" - - php ${MOKO_CLI}/updates_xml_build.php \ - --path . --version "${VERSION}" --stability "${STABILITY}" \ - --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \ - ${SHA_FLAG} - - # Commit and push - if ! git diff --quiet updates.xml 2>/dev/null; then - git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" - git config --local user.name "gitea-actions[bot]" - git add updates.xml - git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]" - git push origin HEAD 2>&1 || echo "WARNING: push failed" - fi - - - name: "Sync updates.xml to all branches" - if: steps.platform.outputs.platform == 'joomla' - run: | - CURRENT_BRANCH="${{ github.ref_name }}" - git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" - git config --local user.name "gitea-actions[bot]" - - for BRANCH in main dev; do - [ "$BRANCH" = "$CURRENT_BRANCH" ] && continue - echo "Syncing updates.xml -> ${BRANCH}" - git fetch origin "${BRANCH}" 2>/dev/null || continue - git checkout "origin/${BRANCH}" -- updates.xml 2>/dev/null || continue - git checkout "${CURRENT_BRANCH}" -- updates.xml - if ! git diff --quiet updates.xml 2>/dev/null; then - git add updates.xml - git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]" - git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed" - fi - git checkout "${CURRENT_BRANCH}" 2>/dev/null - done - - - name: "Delete lesser pre-release channels (cascade)" - continue-on-error: true - run: | - API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" - - php ${MOKO_CLI}/release_cascade.php \ - --stability "${{ steps.meta.outputs.stability }}" \ - --token "${TOKEN}" \ - --api-base "${API_BASE}" - - - name: Summary - if: always() - run: | - VERSION="${{ steps.meta.outputs.version }}" - STABILITY="${{ steps.meta.outputs.stability }}" - ZIP_NAME="${{ steps.meta.outputs.zip_name }}" - SHA256="${{ steps.package.outputs.sha256_zip }}" - echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY - echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY - echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY - echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY - echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY +# Copyright (C) 2026 Moko Consulting +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: moko-platform.Release +# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform +# PATH: /templates/workflows/universal/pre-release.yml.template +# VERSION: 05.01.00 +# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch + +name: "Universal: Pre-Release" + +on: + pull_request: + types: [closed] + branches: + - dev + pull_request_target: + types: [synchronize, opened, reopened] + branches: + - main + workflow_dispatch: + inputs: + stability: + description: 'Pre-release channel' + required: true + type: choice + options: + - development + - alpha + - beta + - release-candidate + +permissions: + contents: write + +env: + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} + GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} + +jobs: + build: + name: "Build Pre-Release (${{ inputs.stability || 'development' }})" + runs-on: release + if: >- + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev') || + (github.event_name == 'pull_request_target' && github.event.pull_request.base.ref == 'main') + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.MOKOGITEA_TOKEN }} + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || '' }} + + - name: Setup moko-platform tools + env: + MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting + run: | + # Use pre-installed /opt/moko-platform if available (updated by cron every 6h) + if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/cli/manifest_element.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then + echo Using pre-installed /opt/moko-platform + echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV + else + echo Falling back to fresh clone + if ! command -v composer > /dev/null 2>&1; then + sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1 + fi + rm -rf /tmp/moko-platform-api + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git + git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api + cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet + echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV + fi + + - name: Detect platform + id: platform + run: | + php ${MOKO_CLI}/manifest_read.php --path . --github-output + + - name: Resolve metadata and bump version + id: meta + run: | + # Auto-detect stability: RC for PRs targeting main, else use input or default to development + if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then + STABILITY="release-candidate" + else + STABILITY="${{ inputs.stability || 'development' }}" + fi + + case "$STABILITY" in + development) SUFFIX="-dev"; TAG="development" ;; + alpha) SUFFIX="-alpha"; TAG="alpha" ;; + beta) SUFFIX="-beta"; TAG="beta" ;; + release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;; + esac + + # Bump version via CLI: patch for dev/alpha/beta, minor for RC + case "$STABILITY" in + release-candidate) BUMP="minor" ;; + *) BUMP="patch" ;; + esac + + php ${MOKO_CLI}/version_bump.php --path . $([ "$BUMP" = "minor" ] && echo "--minor") 2>/dev/null || true + + # Set stability suffix and verify consistency + VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "00.00.01") + VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//') + + php ${MOKO_CLI}/version_set_platform.php \ + --path . --version "$VERSION" --branch "${{ github.ref_name }}" --stability "$STABILITY" 2>/dev/null || true + php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true + + # Ensure licensing tags (updateservers, dlid) if enabled in manifest.xml + php ${MOKO_CLI}/manifest_licensing.php --path . --fix 2>/dev/null || true + + # Append suffix for output + if [ -n "$SUFFIX" ]; then + VERSION="${VERSION}${SUFFIX}" + fi + + # Commit version bump + git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" + git config --local user.name "gitea-actions[bot]" + git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" + git add -A + git diff --cached --quiet || { + git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]" + git push origin HEAD 2>&1 + } + + # Auto-detect element via manifest_element.php + php ${MOKO_CLI}/manifest_element.php \ + --path . --version "$VERSION" --stability "$STABILITY" \ + --repo "${GITEA_REPO}" --github-output + + # Read back element outputs + EXT_ELEMENT=$(grep '^ext_element=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2) + ZIP_NAME=$(grep '^zip_name=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2) + [ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') + [ -z "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip" + + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT" + echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT" + echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT" + + echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ===" + + - name: Create release + id: release + run: | + TAG="${{ steps.meta.outputs.tag }}" + VERSION="${{ steps.meta.outputs.version }}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + php ${MOKO_CLI}/release_create.php \ + --path . --version "$VERSION" --tag "$TAG" \ + --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ + --repo "${GITEA_REPO}" --branch dev --prerelease + + - name: Update release notes from CHANGELOG.md + run: | + TAG="${{ steps.meta.outputs.tag }}" + VERSION="${{ steps.meta.outputs.version }}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + + # Extract [Unreleased] section from changelog (everything between [Unreleased] and next ## heading) + if [ -f "CHANGELOG.md" ]; then + NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md) + [ -z "$NOTES" ] && NOTES="Release ${VERSION}" + else + NOTES="Release ${VERSION}" + fi + + # Update release body via API + RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ + "${API_BASE}/releases/tags/${TAG}" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true) + + if [ -n "$RELEASE_ID" ]; then + python3 -c " + import json, urllib.request + body = open('/dev/stdin').read() + payload = json.dumps({'body': body}).encode() + req = urllib.request.Request( + '${API_BASE}/releases/${RELEASE_ID}', + data=payload, method='PATCH', + headers={ + 'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}', + 'Content-Type': 'application/json' + }) + urllib.request.urlopen(req) + " <<< "$NOTES" + echo "Release notes updated from CHANGELOG.md" + fi + + - name: Build package and upload + id: package + run: | + VERSION="${{ steps.meta.outputs.version }}" + TAG="${{ steps.meta.outputs.tag }}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + php ${MOKO_CLI}/release_package.php \ + --path . --version "$VERSION" --tag "$TAG" \ + --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ + --repo "${GITEA_REPO}" --output /tmp || true + + # updates.xml is generated dynamically by MokoGitea license server + # No need to build, commit, or sync updates.xml from workflows + + - name: "Delete lesser pre-release channels (cascade)" + continue-on-error: true + run: | + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" + + php ${MOKO_CLI}/release_cascade.php \ + --stability "${{ steps.meta.outputs.stability }}" \ + --token "${TOKEN}" \ + --api-base "${API_BASE}" + + - name: Summary + if: always() + run: | + VERSION="${{ steps.meta.outputs.version }}" + STABILITY="${{ steps.meta.outputs.stability }}" + ZIP_NAME="${{ steps.meta.outputs.zip_name }}" + SHA256="${{ steps.package.outputs.sha256_zip }}" + echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY + echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY + echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY diff --git a/.mokogitea/workflows/update-submodule-waas.yml b/.mokogitea/workflows/update-submodule-waas.yml deleted file mode 100644 index 39461ce..0000000 --- a/.mokogitea/workflows/update-submodule-waas.yml +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# BRIEF: Update MokoOnyx submodule in MokoWaas on main and dev branches - -name: "Update MokoWaas Submodule" - -on: - release: - types: [published] - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - WAAS_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} - WAAS_REPO: MokoWaaS - # Path where MokoOnyx lives as a submodule inside MokoWaaS - SUBMODULE_PATH: src/packages/tpl_mokoonyx - -permissions: - contents: read - -jobs: - update-submodule: - name: "Update submodule on ${{ matrix.branch }}" - runs-on: ubuntu-latest - strategy: - matrix: - branch: [main, dev] - fail-fast: false - - steps: - - name: Get release info - id: release - run: | - TAG="${{ github.event.release.tag_name }}" - IS_PRE="${{ github.event.release.prerelease }}" - echo "tag=${TAG}" >> $GITHUB_OUTPUT - echo "prerelease=${IS_PRE}" >> $GITHUB_OUTPUT - echo "Release tag: ${TAG} (prerelease: ${IS_PRE})" - - # Skip pre-releases (RC) — only update on stable releases - - name: Skip pre-releases - if: steps.release.outputs.prerelease == 'true' - run: | - echo "Skipping pre-release ${TAG} — only stable releases update MokoWaas" - exit 0 - - - name: Clone MokoWaas - if: steps.release.outputs.prerelease != 'true' - run: | - git clone --branch "${{ matrix.branch }}" --depth 1 --recurse-submodules \ - "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${WAAS_ORG}/${WAAS_REPO}.git" \ - waas - env: - GIT_TERMINAL_PROMPT: 0 - - - name: Configure git - if: steps.release.outputs.prerelease != 'true' - working-directory: waas - run: | - git config user.email "gitea-actions[bot]@mokoconsulting.tech" - git config user.name "gitea-actions[bot]" - git remote set-url origin \ - "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${WAAS_ORG}/${WAAS_REPO}.git" - - - name: Update submodule to release tag - if: steps.release.outputs.prerelease != 'true' - working-directory: waas - run: | - TAG="${{ steps.release.outputs.tag }}" - SUBPATH="${SUBMODULE_PATH}" - - # Verify submodule exists - if [ ! -f ".gitmodules" ] || ! grep -q "${SUBPATH}" .gitmodules; then - echo "::error::Submodule '${SUBPATH}' not found in .gitmodules on ${{ matrix.branch }}" - exit 1 - fi - - # Fetch the tag in the submodule and update to it - cd "${SUBPATH}" - git fetch origin "refs/tags/${TAG}:refs/tags/${TAG}" --depth 1 - git checkout "${TAG}" - cd - - - # Stage the submodule pointer change - git add "${SUBPATH}" - - # Only commit if there's actually a change - if git diff --cached --quiet; then - echo "Submodule already at ${TAG} on ${{ matrix.branch }} — nothing to do" - else - git commit -m "chore: update MokoOnyx submodule to ${TAG} - -Authored-by: Moko Consulting" - git push origin "${{ matrix.branch }}" - echo "Updated MokoOnyx to ${TAG} on ${{ matrix.branch }}" - fi - - - name: Summary - if: always() && steps.release.outputs.prerelease != 'true' - run: | - TAG="${{ steps.release.outputs.tag }}" - echo "## MokoWaas Submodule Update (${{ matrix.branch }})" >> $GITHUB_STEP_SUMMARY - echo "Updated \`${SUBMODULE_PATH}\` to \`${TAG}\`" >> $GITHUB_STEP_SUMMARY diff --git a/CHANGELOG.md b/CHANGELOG.md index 4561fb2..ce16c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,16 +8,13 @@ DEFGROUP: Joomla.Template.Site INGROUP: MokoOnyx.Documentation PATH: ./CHANGELOG.md - VERSION: 02.20.00 + VERSION: 02.19.07 BRIEF: Changelog file documenting version history of MokoOnyx --> -# Changelog — MokoOnyx (VERSION: 02.20.00) - +# Changelog — MokoOnyx (VERSION: 02.19.07) ## [Unreleased] -## [02.20.00] --- 2026-06-04 - ### Fixed - Strip Joomla-injected `p-2` padding class from Font Awesome icons in all menu overrides (default, mainmenu, horizontal) diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 6bf367c..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,42 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code when working with this repository. - -## Project Overview - -**MokoOnyx** -- MokoOnyx - Joomla site template (successor to MokoCassiopeia) - -| Field | Value | -|---|---| -| **Platform** | joomla | -| **Language** | PHP | -| **Default branch** | main | -| **License** | GPL-3.0-or-later | -| **Wiki** | [MokoOnyx Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/wiki) | -| **Standards** | [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) | - -## Common Commands - -```bash -composer install # Install PHP dependencies -``` - -## Architecture - -This is a Joomla extension. Key directories: -- `src/` -- extension source (deployed to Joomla) -- `src/*.xml` -- manifest file (version, files, params) -- `src/src/` or `src/services/` -- PHP classes -- `src/language/` -- translation strings -- `src/media/` -- CSS/JS/images - -## Rules - -- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`) - -- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, or `*.min.css`/`*.min.js` -- **Attribution**: use `Authored-by: Moko Consulting` in commits -- **Branch strategy**: develop on `dev`, merge to `main` for release -- **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper for Joomla templates) -- **Wiki**: documentation lives in the Gitea wiki, not in `docs/` files -- **Standards**: this repo follows [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) diff --git a/SECURITY.md b/SECURITY.md index 46cba7c..343ccbc 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,7 +10,7 @@ INGROUP: MokoOnyx.Governance REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx FILE: SECURITY.md - VERSION: 02.20.00 + VERSION: 02.19.07 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. diff --git a/src/helper/migrate.php b/src/helper/migrate.php index b57d956..1c9e088 100644 --- a/src/helper/migrate.php +++ b/src/helper/migrate.php @@ -236,11 +236,11 @@ use Joomla\CMS\Log\Log; // Update the update server try { - $onyxUpdatesUrl = 'https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml'; + $onyxUpdatesUrl = 'https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/updates.xml'; $query = $db->getQuery(true) ->update('#__update_sites') ->set($db->quoteName('location') . ' = ' . $db->quote($onyxUpdatesUrl)) - ->set($db->quoteName('name') . ' = ' . $db->quote($newDisplay)) + ->set($db->quoteName('name') . ' = ' . $db->quote('Template - MokoOnyx')) ->where($db->quoteName('location') . ' LIKE ' . $db->quote('%MokoCassiopeia%')); $db->setQuery($query)->execute(); $n = $db->getAffectedRows(); diff --git a/src/html/layouts/joomla/module/card.php b/src/html/layouts/joomla/module/card.php index 316554d..0c1a69c 100644 --- a/src/html/layouts/joomla/module/card.php +++ b/src/html/layouts/joomla/module/card.php @@ -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.19.07 * BRIEF: Custom card module chrome — renders module titles for all modules */ diff --git a/src/html/layouts/mokoonyx/article-metadata.php b/src/html/layouts/mokoonyx/article-metadata.php index 17812e1..e80034c 100644 --- a/src/html/layouts/mokoonyx/article-metadata.php +++ b/src/html/layouts/mokoonyx/article-metadata.php @@ -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.19.07 * BRIEF: Article metadata footer layout -- renders jcfields grouped by field group */ diff --git a/src/media/css/a11y-high-contrast.css b/src/media/css/a11y-high-contrast.css index e9e2471..2bd790d 100644 --- a/src/media/css/a11y-high-contrast.css +++ b/src/media/css/a11y-high-contrast.css @@ -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.19.07 * BRIEF: High-contrast stylesheet for accessibility toolbar */ diff --git a/src/script.php b/src/script.php index 35f6641..5496c17 100644 --- a/src/script.php +++ b/src/script.php @@ -34,6 +34,9 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface private const OLD_DISPLAY = 'MokoCassiopeia'; private const NEW_DISPLAY = 'MokoOnyx'; + + + public function preflight(string $type, InstallerAdapter $parent): bool { if (version_compare(PHP_VERSION, self::MIN_PHP, '<')) { @@ -83,11 +86,16 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface public function uninstall(InstallerAdapter $parent): bool { $this->logMessage('MokoOnyx template uninstalled.'); + $this->saveDownloadKey(); + return true; } public function postflight(string $type, InstallerAdapter $parent): bool { + $this->restoreDownloadKey(); + $this->warnMissingLicenseKey(); + if ($type === 'install' || $type === 'update') { $this->migrateFromCassiopeia(); $this->replaceCassiopeiaReferences(); @@ -533,6 +541,37 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface } } + // Remove faulty "template-mokoonyx" duplicate (wrong element name from bad install) + $faultyId = (int) $db->setQuery( + $db->getQuery(true) + ->select('extension_id') + ->from('#__extensions') + ->where($db->quoteName('element') . ' = ' . $db->quote('template-mokoonyx')) + ->where($db->quoteName('type') . ' = ' . $db->quote('template')) + )->loadResult(); + + if ($faultyId) { + $db->setQuery( + $db->getQuery(true) + ->delete('#__update_sites_extensions') + ->where('extension_id = ' . $faultyId) + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete('#__extensions') + ->where('extension_id = ' . $faultyId) + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete('#__template_styles') + ->where($db->quoteName('template') . ' = ' . $db->quote('template-mokoonyx')) + )->execute(); + + $this->logMessage('Removed faulty template-mokoonyx duplicate extension.'); + } + // Remove stale MokoCassiopeia if not set as default $oldExt = (int) $db->setQuery( $db->getQuery(true) @@ -653,4 +692,92 @@ class Tpl_MokoonyxInstallerScript implements InstallerScriptInterface Log::add($message, $priorities[$priority] ?? Log::INFO, 'mokoonyx'); } + + + private ?string $savedDownloadKey = null; + + private function saveDownloadKey(): void + { + try + { + $db = \Joomla\CMS\Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->select($db->quoteName('us.extra_query')) + ->from($db->quoteName('#__update_sites', 'us')) + ->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id') + ->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id') + ->where($db->quoteName('e.element') . ' = ' . $db->quote('mokoonyx')) + ->setLimit(1) + ); + $key = $db->loadResult(); + if (!empty($key)) { $this->savedDownloadKey = $key; } + } + catch (\Throwable $e) {} + } + + private function restoreDownloadKey(): void + { + if ($this->savedDownloadKey === null) { return; } + + try + { + $db = \Joomla\CMS\Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->select($db->quoteName('us.update_site_id')) + ->from($db->quoteName('#__update_sites', 'us')) + ->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id') + ->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id') + ->where($db->quoteName('e.element') . ' = ' . $db->quote('mokoonyx')) + ->setLimit(1) + ); + $siteId = (int) $db->loadResult(); + if ($siteId > 0) + { + $db->setQuery( + $db->getQuery(true) + ->update($db->quoteName('#__update_sites')) + ->set($db->quoteName('extra_query') . ' = ' . $db->quote($this->savedDownloadKey)) + ->where($db->quoteName('update_site_id') . ' = ' . $siteId) + )->execute(); + } + } + catch (\Throwable $e) {} + } + + private function warnMissingLicenseKey(): void + { + try + { + $db = \Joomla\CMS\Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query')]) + ->from($db->quoteName('#__update_sites')) + ->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoOnyx%') . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoOnyx%') . ')') + ->setLimit(1) + ); + $site = $db->loadObject(); + + if ($site) + { + $eq = (string) ($site->extra_query ?? ''); + if (!empty($eq) && strpos($eq, 'dlid=') !== false) { parse_str($eq, $p); if (!empty($p['dlid'])) { return; } } + $editUrl = 'index.php?option=com_installer&task=updatesite.edit&update_site_id=' . (int) $site->update_site_id; + } + else + { + $editUrl = 'index.php?option=com_installer&view=updatesites'; + } + + \Joomla\CMS\Factory::getApplication()->enqueueMessage( + 'Moko Consulting License Key Required — ' + . 'No download key is configured. Updates will not be available until a valid license key is entered. ' + . 'Enter License Key', + 'warning' + ); + } + catch (\Throwable $e) {} + } } diff --git a/src/templateDetails.xml b/src/templateDetails.xml index a8bd706..d2b770d 100644 --- a/src/templateDetails.xml +++ b/src/templateDetails.xml @@ -35,7 +35,7 @@ mokoonyx - 02.20.00 + 02.19.07-dev script.php 2026-05-16 Jonathan Miller || Moko Consulting diff --git a/updates.xml b/updates.xml deleted file mode 100644 index eb3c962..0000000 --- a/updates.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - Template - MokoOnyx - Template - MokoOnyx development build. - mokoonyx - template - site - 02.19.06-dev - 2026-06-04 - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/development - - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.19.06-dev.zip - - 718dd24295a5c8e3a0c855b01f86bf619bae84a4f7ab6e037c5cd5bfaadb2e30 - dev - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md - Moko Consulting - https://mokoconsulting.tech - - 8.1.0 - - - Template - MokoOnyx - Template - MokoOnyx stable build. - mokoonyx - template - site - 02.20.00 - 2026-06-04 - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable - - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.20.00.zip - - 00851a8a0ce9f64b873cbfbf4495422e78788d303ad5a4ac13f48122a8bc9e30 - stable - https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md - Moko Consulting - https://mokoconsulting.tech - - 8.1.0 - -