From 9666a874ca24d5d40c8a1191846c4f38985720be Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 21 Jun 2026 11:13:11 -0500 Subject: [PATCH 01/59] =?UTF-8?q?feat:=20Form990Helper=20=E2=80=94=20IRS?= =?UTF-8?q?=20Form=20990=20data=20prep,=20revenue/expense=20classification?= =?UTF-8?q?,=20compensation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/Form990Helper.php | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 source/packages/plg_system_mokosuitenpo/src/Helper/Form990Helper.php diff --git a/source/packages/plg_system_mokosuitenpo/src/Helper/Form990Helper.php b/source/packages/plg_system_mokosuitenpo/src/Helper/Form990Helper.php new file mode 100644 index 0000000..cb8c557 --- /dev/null +++ b/source/packages/plg_system_mokosuitenpo/src/Helper/Form990Helper.php @@ -0,0 +1,124 @@ +get(DatabaseInterface::class); + + // Contributions (Line 1) + $db->setQuery($db->getQuery(true) + ->select('COALESCE(SUM(amount), 0) AS total') + ->from('#__mokosuitenpo_donations') + ->where('YEAR(donation_date) = ' . $fiscalYear)); + $contributions = (float) $db->loadResult(); + + // Membership dues (Line 1b) + $db->setQuery($db->getQuery(true) + ->select('COALESCE(SUM(amount), 0) AS total') + ->from('#__mokosuitenpo_membership_payments') + ->where('YEAR(payment_date) = ' . $fiscalYear)); + $memberDues = (float) $db->loadResult(); + + // Grant revenue (Line 1f) + $db->setQuery($db->getQuery(true) + ->select('COALESCE(SUM(amount_received), 0) AS total') + ->from('#__mokosuitenpo_grant_payments') + ->where('YEAR(received_date) = ' . $fiscalYear)); + $grants = (float) $db->loadResult(); + + // Program service revenue (Line 2) + $db->setQuery($db->getQuery(true) + ->select('COALESCE(SUM(amount), 0) AS total') + ->from('#__mokosuitenpo_program_revenue') + ->where('YEAR(revenue_date) = ' . $fiscalYear)); + $programRevenue = (float) $db->loadResult(); + + // In-kind donations (Line 1g) + $db->setQuery($db->getQuery(true) + ->select('COALESCE(SUM(fair_market_value), 0) AS total') + ->from('#__mokosuitenpo_inkind_donations') + ->where('YEAR(received_at) = ' . $fiscalYear)); + $inKind = (float) $db->loadResult(); + + $totalRevenue = $contributions + $memberDues + $grants + $programRevenue + $inKind; + + return (object) [ + 'fiscal_year' => $fiscalYear, + 'contributions' => round($contributions, 2), + 'membership_dues' => round($memberDues, 2), + 'grants' => round($grants, 2), + 'program_revenue' => round($programRevenue, 2), + 'in_kind' => round($inKind, 2), + 'total_revenue' => round($totalRevenue, 2), + ]; + } + + /** + * Get Part IX expense breakdown (program services, management, fundraising). + */ + public static function getExpenseBreakdown(int $fiscalYear = 0): object + { + $fiscalYear = $fiscalYear ?: (int) date('Y'); + $db = Factory::getContainer()->get(DatabaseInterface::class); + + $db->setQuery($db->getQuery(true) + ->select('classification') + ->select('SUM(amount) AS total') + ->from('#__mokosuitenpo_expenses') + ->where('YEAR(expense_date) = ' . $fiscalYear) + ->group('classification')); + + $rows = $db->loadObjectList('classification') ?: []; + + $program = round((float) ($rows['program_services']->total ?? 0), 2); + $management = round((float) ($rows['management_general']->total ?? 0), 2); + $fundraising = round((float) ($rows['fundraising']->total ?? 0), 2); + $total = $program + $management + $fundraising; + + return (object) [ + 'fiscal_year' => $fiscalYear, + 'program_services' => $program, + 'management_general' => $management, + 'fundraising' => $fundraising, + 'total_expenses' => $total, + 'program_pct' => $total > 0 ? round($program / $total * 100, 1) : 0, + ]; + } + + /** + * Get Part VII compensation data for officers/key employees. + */ + public static function getCompensationSchedule(int $fiscalYear = 0): array + { + $fiscalYear = $fiscalYear ?: (int) date('Y'); + $db = Factory::getContainer()->get(DatabaseInterface::class); + + $db->setQuery($db->getQuery(true) + ->select('cd.name, bm.role AS title, bm.weekly_hours') + ->select('COALESCE(c.base_compensation, 0) AS compensation') + ->select('COALESCE(c.benefits, 0) AS benefits') + ->select('COALESCE(c.other_compensation, 0) AS other') + ->from($db->quoteName('#__mokosuitenpo_board_members', 'bm')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = bm.contact_id') + ->join('LEFT', $db->quoteName('#__mokosuitenpo_compensation', 'c') + . ' ON c.contact_id = bm.contact_id AND c.fiscal_year = ' . $fiscalYear) + ->where($db->quoteName('bm.status') . ' = ' . $db->quote('active')) + ->order('compensation DESC')); + + return $db->loadObjectList() ?: []; + } +} From 2811d50305100ec1eb5740abca1c1a0ee5882ea3 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 21 Jun 2026 16:13:21 +0000 Subject: [PATCH 02/59] chore(version): auto-bump patch 01.07.01-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 45b29f8..2c19c81 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.00 +# VERSION: 01.07.01 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index cda1abd..01d394c 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.00 + 01.07.01 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index c411a90..0fa922e 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.00 + 01.07.01 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 3f0327454b2e7b4f394db14e608f8eac432de5ad Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 21 Jun 2026 16:13:30 +0000 Subject: [PATCH 03/59] chore(version): pre-release bump to 01.07.02-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 2c19c81..beec2b5 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.01 +# VERSION: 01.07.02 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 01d394c..1b2add0 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.01 + 01.07.02 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 0fa922e..7610743 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.01 + 01.07.02 2026-06-11 Moko Consulting hello@mokoconsulting.tech From f3d7233ffd8846f4fa08a6ef71c77a2e805ed837 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 21 Jun 2026 11:53:24 -0500 Subject: [PATCH 04/59] =?UTF-8?q?fix:=20review=20#18=20=E2=80=94=20Recurri?= =?UTF-8?q?ngDonationHelper=20argument=20order=20(fund=5Fid/type=20swapped?= =?UTF-8?q?=20=3D=20TypeError)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/RecurringDonationHelper.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/packages/plg_system_mokosuitenpo/src/Helper/RecurringDonationHelper.php b/source/packages/plg_system_mokosuitenpo/src/Helper/RecurringDonationHelper.php index ec3a1fe..e9b5796 100644 --- a/source/packages/plg_system_mokosuitenpo/src/Helper/RecurringDonationHelper.php +++ b/source/packages/plg_system_mokosuitenpo/src/Helper/RecurringDonationHelper.php @@ -89,10 +89,10 @@ class RecurringDonationHelper DonorHelper::recordDonation( (int) $pledge->donor_id, (float) $pledge->amount, - 'card', (int) $pledge->fund_id, - 0, - 'Recurring pledge #' . $pledge->id + 'card', + null, + ['notes' => 'Recurring pledge #' . $pledge->id] ); // Advance next charge date From 537edf94c4d94e157e34d2fd682f9eee9dfaeb51 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 21 Jun 2026 16:53:41 +0000 Subject: [PATCH 05/59] chore(version): auto-bump patch 01.07.03-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index beec2b5..a775793 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.02 +# VERSION: 01.07.03 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 1b2add0..0aaf9c1 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.02 + 01.07.03 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 7610743..7feb8e0 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.02 + 01.07.03 2026-06-11 Moko Consulting hello@mokoconsulting.tech From b214119c3d00b2bc6980c5ffa079e0d1cc378682 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 21 Jun 2026 16:53:50 +0000 Subject: [PATCH 06/59] chore(version): pre-release bump to 01.07.04-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index a775793..c9afddc 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.03 +# VERSION: 01.07.04 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 0aaf9c1..18a175d 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.03 + 01.07.04 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 7feb8e0..2494ee6 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.03 + 01.07.04 2026-06-11 Moko Consulting hello@mokoconsulting.tech From d24364113b8a5b5a01450286032b0e31f801af0f Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Mon, 22 Jun 2026 22:21:52 -0500 Subject: [PATCH 07/59] =?UTF-8?q?chore:=20fix=20workflows=20=E2=80=94=20re?= =?UTF-8?q?move=20generic=20template=20extras,=20add=20Joomla=20template?= =?UTF-8?q?=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mokogitea/workflows/ci-joomla.yml | 903 +++++++++++++++++++++ .mokogitea/workflows/composer-publish.yml | 76 -- .mokogitea/workflows/deploy-manual.yml | 126 --- .mokogitea/workflows/pr-metadata-check.yml | 71 ++ 4 files changed, 974 insertions(+), 202 deletions(-) create mode 100644 .mokogitea/workflows/ci-joomla.yml delete mode 100644 .mokogitea/workflows/composer-publish.yml delete mode 100644 .mokogitea/workflows/deploy-manual.yml create mode 100644 .mokogitea/workflows/pr-metadata-check.yml diff --git a/.mokogitea/workflows/ci-joomla.yml b/.mokogitea/workflows/ci-joomla.yml new file mode 100644 index 0000000..727f661 --- /dev/null +++ b/.mokogitea/workflows/ci-joomla.yml @@ -0,0 +1,903 @@ +# Copyright (C) 2026 Moko Consulting +# +# This file is part of a Moko Consulting project. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow.Template +# INGROUP: MokoStandards.CI +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# PATH: /templates/workflows/joomla/ci-joomla.yml.template +# VERSION: 04.06.00 +# BRIEF: CI workflow for Joomla extensions — lint, validate, test + +name: "Joomla: Extension CI" + +on: + pull_request: + branches: + - main + - 'dev/**' + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + lint-and-validate: + name: Lint & Validate + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup PHP + run: | + if ! command -v php &> /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 + php -v && composer --version + + - name: Setup mokocli tools + env: + MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.GA_TOKEN || github.token }} + MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }} + run: | + if [ -d "/opt/mokocli" ] || [ -d "/tmp/mokocli" ]; then + echo "mokocli already available on runner — skipping clone" + else + git clone --depth 1 --branch main --quiet \ + "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git" \ + /tmp/mokocli 2>/dev/null || echo "mokocli clone skipped — continuing without it" + fi + + - name: Install dependencies + env: + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || secrets.GA_TOKEN || github.token }}"}}' + run: | + if [ -f "composer.json" ]; then + composer install \ + --no-interaction \ + --prefer-dist \ + --optimize-autoloader + else + echo "No composer.json found — skipping dependency install" + fi + + - name: PHP syntax check + run: | + ERRORS=0 + for DIR in src/ htdocs/; do + if [ -d "$DIR" ]; then + FOUND=1 + while IFS= read -r -d '' FILE; do + OUTPUT=$(php -l "$FILE" 2>&1) + if echo "$OUTPUT" | grep -q "Parse error"; then + echo "::error file=${FILE}::${OUTPUT}" + ERRORS=$((ERRORS + 1)) + fi + done < <(find "$DIR" -name "*.php" -print0) + fi + done + echo "### PHP Syntax Check" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} syntax error(s) found.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "All PHP files passed syntax check." >> $GITHUB_STEP_SUMMARY + fi + + - name: XML manifest validation + run: | + echo "### XML Manifest Validation" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + # Find the extension manifest (XML with /dev/null; then + MANIFEST="$XML_FILE" + break + fi + done + + if [ -z "$MANIFEST" ]; then + echo "No Joomla extension manifest found (XML file with \`> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Manifest found: \`${MANIFEST}\`" >> $GITHUB_STEP_SUMMARY + + # Validate well-formed XML + php -r " + \$xml = @simplexml_load_file('$MANIFEST'); + if (\$xml === false) { + echo 'INVALID'; + exit(1); + } + echo 'VALID'; + " > /tmp/xml_result 2>&1 + XML_RESULT=$(cat /tmp/xml_result) + if [ "$XML_RESULT" != "VALID" ]; then + echo "Manifest is not well-formed XML." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Manifest is well-formed XML." >> $GITHUB_STEP_SUMMARY + fi + + # Check required tags: name, version, author + for TAG in name version author; do + if ! grep -q "<${TAG}>" "$MANIFEST" 2>/dev/null; then + echo "Missing required tag: \`<${TAG}>\`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Found required tag: \`<${TAG}>\`" >> $GITHUB_STEP_SUMMARY + fi + done + + # Namespace is required for components/plugins but not packages + EXT_TYPE=$(grep -oP ']*\btype="\K[^"]+' "$MANIFEST" | head -1) + if [ "$EXT_TYPE" != "package" ]; then + if ! grep -q "/dev/null; then + echo "Missing required tag: \`\` (required for Joomla 5+ ${EXT_TYPE} extensions)" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Found required tag: \`\`" >> $GITHUB_STEP_SUMMARY + fi + else + echo "Package extension — \`\` not required." >> $GITHUB_STEP_SUMMARY + fi + fi + + if [ "${ERRORS}" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "**${ERRORS} manifest issue(s) found.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Manifest validation passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Check language files referenced in manifest + run: | + echo "### Language File Check" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + MANIFEST="" + for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do + if grep -q "/dev/null; then + MANIFEST="$XML_FILE" + break + fi + done + + if [ -n "$MANIFEST" ]; then + # Extract language file references from manifest + LANG_FILES=$(grep -oP 'language\s+tag="[^"]*"[^>]*>\K[^<]+' "$MANIFEST" 2>/dev/null || true) + if [ -z "$LANG_FILES" ]; then + echo "No language file references found in manifest — skipping." >> $GITHUB_STEP_SUMMARY + else + while IFS= read -r LANG_FILE; do + LANG_FILE=$(echo "$LANG_FILE" | xargs) + if [ -z "$LANG_FILE" ]; then + continue + fi + # Check in common locations + FOUND=0 + for BASE in "." "src" "htdocs"; do + if [ -f "${BASE}/${LANG_FILE}" ]; then + FOUND=1 + break + fi + done + if [ "$FOUND" -eq 0 ]; then + echo "Missing language file: \`${LANG_FILE}\`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Language file present: \`${LANG_FILE}\`" >> $GITHUB_STEP_SUMMARY + fi + done <<< "$LANG_FILES" + fi + else + echo "No manifest found — skipping language check." >> $GITHUB_STEP_SUMMARY + fi + + if [ "${ERRORS}" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "**${ERRORS} missing language file(s).**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Language file check passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Check index.html files in directories + run: | + echo "### Index.html Check" >> $GITHUB_STEP_SUMMARY + MISSING=0 + CHECKED=0 + + for DIR in src/ htdocs/; do + if [ -d "$DIR" ]; then + while IFS= read -r -d '' SUBDIR; do + CHECKED=$((CHECKED + 1)) + if [ ! -f "${SUBDIR}/index.html" ]; then + echo "Missing index.html in: \`${SUBDIR}\`" >> $GITHUB_STEP_SUMMARY + MISSING=$((MISSING + 1)) + fi + done < <(find "$DIR" -type d -print0) + fi + done + + if [ "${CHECKED}" -eq 0 ]; then + echo "No src/ or htdocs/ directories found — skipping." >> $GITHUB_STEP_SUMMARY + elif [ "${MISSING}" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "**${MISSING} director(ies) missing index.html out of ${CHECKED} checked.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "All ${CHECKED} directories contain index.html." >> $GITHUB_STEP_SUMMARY + fi + + - name: Check config.xml and access.xml for components + run: | + echo "### Component Config & ACL Check" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + # Find all component manifests (XML with type="component") + COMP_MANIFESTS=$(find . -maxdepth 4 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*" -exec grep -l ']*type="component"' {} ; 2>/dev/null || true) + + if [ -z "$COMP_MANIFESTS" ]; then + echo "No component extensions found — skipping." >> $GITHUB_STEP_SUMMARY + else + for MANIFEST in $COMP_MANIFESTS; do + COMP_DIR=$(dirname "$MANIFEST") + COMP_NAME=$(basename "$COMP_DIR") + echo "Component: `${COMP_NAME}` (manifest: `${MANIFEST}`)" >> $GITHUB_STEP_SUMMARY + + # Check access.xml exists + ACCESS_FILE=$(find "$COMP_DIR" -name "access.xml" -not -path "./.git/*" 2>/dev/null | head -1) + if [ -z "$ACCESS_FILE" ]; then + echo "- Missing `access.xml` — ACL permissions will not work." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + if command -v php &> /dev/null; then + if ! php -r "@simplexml_load_file('$ACCESS_FILE') ?: exit(1);" 2>/dev/null; then + echo "- `access.xml` is not well-formed XML." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + for ACTION in core.admin core.manage; do + if ! grep -q "name=\"${ACTION}\"" "$ACCESS_FILE" 2>/dev/null; then + echo "- `access.xml` missing required action: `${ACTION}`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done + echo "- `access.xml`: valid" >> $GITHUB_STEP_SUMMARY + fi + fi + fi + + # Check config.xml exists + CONFIG_FILE=$(find "$COMP_DIR" -name "config.xml" -not -path "./.git/*" 2>/dev/null | head -1) + if [ -z "$CONFIG_FILE" ]; then + echo "- Missing `config.xml` — component Options page will be empty." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + if command -v php &> /dev/null; then + if ! php -r "@simplexml_load_file('$CONFIG_FILE') ?: exit(1);" 2>/dev/null; then + echo "- `config.xml` is not well-formed XML." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "- `config.xml`: valid" >> $GITHUB_STEP_SUMMARY + fi + fi + fi + done + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} config/ACL issue(s) found.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Component config & ACL check passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: SQL schema validation + run: | + echo "### SQL Schema Validation" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + # Find SQL files in source/htdocs + SQL_FILES=$(find . -name "*.sql" -path "*/sql/*" -not -path "./.git/*" -not -path "./vendor/*" 2>/dev/null) + if [ -z "$SQL_FILES" ]; then + echo "No SQL files found — skipping." >> $GITHUB_STEP_SUMMARY + else + echo "Found $(echo "$SQL_FILES" | wc -l) SQL file(s)" >> $GITHUB_STEP_SUMMARY + + for FILE in $SQL_FILES; do + # Basic syntax check: balanced parentheses, no empty files + SIZE=$(wc -c < "$FILE" | tr -d ' ') + if [ "$SIZE" -eq 0 ]; then + echo "- Empty SQL file: \`${FILE}\`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + continue + fi + + # Check for common SQL errors + if grep -qP '^\s*$' "$FILE" && [ "$SIZE" -lt 5 ]; then + echo "- Whitespace-only SQL file: \`${FILE}\`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + continue + fi + + echo "- \`${FILE}\`: ${SIZE} bytes" >> $GITHUB_STEP_SUMMARY + done + + # Check update SQL files follow version numbering pattern + UPDATE_DIR=$(find . -path "*/sql/updates/mysql" -type d -not -path "./.git/*" 2>/dev/null | head -1) + if [ -n "$UPDATE_DIR" ]; then + BAD_NAMES=0 + for UFILE in "$UPDATE_DIR"/*.sql; do + [ ! -f "$UFILE" ] && continue + BASENAME=$(basename "$UFILE" .sql) + if ! echo "$BASENAME" | grep -qP '^\d+\.\d+\.\d+'; then + echo "- Update file \`${UFILE}\` does not follow version naming (expected X.Y.Z.sql)" >> $GITHUB_STEP_SUMMARY + BAD_NAMES=$((BAD_NAMES + 1)) + fi + done + if [ "$BAD_NAMES" -gt 0 ]; then + ERRORS=$((ERRORS + BAD_NAMES)) + fi + fi + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} SQL issue(s) found.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**SQL schema validation passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Manifest file references check + run: | + echo "### Manifest File References" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + MANIFEST="" + for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do + if grep -q "/dev/null; then + MANIFEST="$XML_FILE" + break + fi + done + + if [ -z "$MANIFEST" ]; then + echo "No manifest found — skipping." >> $GITHUB_STEP_SUMMARY + else + MANIFEST_DIR=$(dirname "$MANIFEST") + + # Check references + FILENAMES=$(grep -oP ']*>\K[^<]+' "$MANIFEST" 2>/dev/null || true) + for F in $FILENAMES; do + if [ ! -f "${MANIFEST_DIR}/${F}" ] && [ ! -d "${MANIFEST_DIR}/${F}" ]; then + echo "- Missing: \`${F}\` (referenced in manifest)" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done + + # Check references + FOLDERS=$(grep -oP ']*>\K[^<]+' "$MANIFEST" 2>/dev/null || true) + for F in $FOLDERS; do + if [ ! -d "${MANIFEST_DIR}/${F}" ]; then + echo "- Missing folder: \`${F}\` (referenced in manifest)" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done + + # Check references in package manifests (ZIP files won't exist in source) + EXT_TYPE=$(grep -oP ']*\btype="\K[^"]+' "$MANIFEST" | head -1) + if [ "$EXT_TYPE" != "package" ]; then + FILES=$(grep -oP ']*>\K[^<]+' "$MANIFEST" 2>/dev/null || true) + for F in $FILES; do + if [ ! -f "${MANIFEST_DIR}/${F}" ]; then + echo "- Missing file: \`${F}\` (referenced in manifest)" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done + fi + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} missing file reference(s).**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Manifest file references check passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Form XML validation + run: | + echo "### Form XML Validation" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + FORM_FILES=$(find . -name "*.xml" -path "*/forms/*" -not -path "./.git/*" -not -path "./vendor/*" 2>/dev/null) + if [ -z "$FORM_FILES" ]; then + echo "No form XML files found — skipping." >> $GITHUB_STEP_SUMMARY + else + echo "Found $(echo "$FORM_FILES" | wc -l) form file(s)" >> $GITHUB_STEP_SUMMARY + for FILE in $FORM_FILES; do + if command -v php &> /dev/null; then + if ! php -r "@simplexml_load_file('$FILE') ?: exit(1);" 2>/dev/null; then + echo "- \`${FILE}\`: malformed XML" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + # Check for valid Joomla form structure + if ! grep -qE '/dev/null; then + echo "- \`${FILE}\`: no \`
\`, \`\`, or \`
\` elements found" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "- \`${FILE}\`: valid" >> $GITHUB_STEP_SUMMARY + fi + fi + fi + done + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} form XML issue(s).**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Form XML validation passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: Deprecated Joomla API check + continue-on-error: true + run: | + echo "### Deprecated Joomla API Check" >> $GITHUB_STEP_SUMMARY + WARNINGS=0 + + SRC_DIR="" + for DIR in source/ src/ htdocs/; do + [ -d "$DIR" ] && SRC_DIR="$DIR" && break + done + + if [ -z "$SRC_DIR" ]; then + echo "No source directory found — skipping." >> $GITHUB_STEP_SUMMARY + else + # Joomla 3/4 deprecated patterns that break in Joomla 6 + PATTERNS=( + 'JFactory::' + 'JText::' + 'JHtml::' + 'JRoute::' + 'JUri::' + 'JLog::' + 'JTable::' + 'JInput' + 'CMSFactory::\$application' + 'JApplicationCms' + ) + + for PATTERN in "${PATTERNS[@]}"; do + HITS=$(grep -rnl "$PATTERN" "$SRC_DIR" --include="*.php" 2>/dev/null || true) + if [ -n "$HITS" ]; then + COUNT=$(echo "$HITS" | wc -l) + echo "- \`${PATTERN}\` found in ${COUNT} file(s)" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + COUNT)) + fi + done + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "$WARNINGS" -gt 0 ]; then + echo "**${WARNINGS} deprecated API usage(s) found.** These will break in Joomla 6." >> $GITHUB_STEP_SUMMARY + else + echo "**No deprecated APIs found.**" >> $GITHUB_STEP_SUMMARY + fi + fi + + - name: Template output escaping check + continue-on-error: true + run: | + echo "### Template Output Escaping" >> $GITHUB_STEP_SUMMARY + WARNINGS=0 + + TMPL_FILES=$(find . -name "*.php" -path "*/tmpl/*" -not -path "./.git/*" -not -path "./vendor/*" 2>/dev/null) + if [ -z "$TMPL_FILES" ]; then + echo "No template files found — skipping." >> $GITHUB_STEP_SUMMARY + else + echo "Found $(echo "$TMPL_FILES" | wc -l) template file(s)" >> $GITHUB_STEP_SUMMARY + + for FILE in $TMPL_FILES; do + # Check for unescaped output: or echo $var without escape() + UNESCAPED=$(grep -nP '<\?=\s*\$(?!this->escape)' "$FILE" 2>/dev/null || true) + if [ -n "$UNESCAPED" ]; then + HITS=$(echo "$UNESCAPED" | wc -l) + echo "- \`${FILE}\`: ${HITS} unescaped \`\` output(s) — use \`escape(\$var) ?>\`" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + HITS)) + fi + + # Check for echo without escaping in template context + RAW_ECHO=$(grep -nP '^\s*echo\s+\$(?!this->escape)' "$FILE" 2>/dev/null || true) + if [ -n "$RAW_ECHO" ]; then + HITS=$(echo "$RAW_ECHO" | wc -l) + echo "- \`${FILE}\`: ${HITS} raw \`echo \$var\` — consider \`echo \$this->escape(\$var)\`" >> $GITHUB_STEP_SUMMARY + WARNINGS=$((WARNINGS + HITS)) + fi + done + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "$WARNINGS" -gt 0 ]; then + echo "**${WARNINGS} potential XSS risk(s) in templates.** Review unescaped output." >> $GITHUB_STEP_SUMMARY + else + echo "**All template output appears properly escaped.**" >> $GITHUB_STEP_SUMMARY + fi + fi + + - name: Namespace consistency check + run: | + echo "### Namespace Consistency" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + # Find component/plugin manifests with tags + MANIFESTS=$(find . -maxdepth 4 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*" -exec grep -l '/dev/null || true) + + if [ -z "$MANIFESTS" ]; then + echo "No manifests with \`\` found — skipping." >> $GITHUB_STEP_SUMMARY + else + for MANIFEST in $MANIFESTS; do + NS_PATH=$(grep -oP ']*>\K[^<]+' "$MANIFEST" 2>/dev/null | head -1) + [ -z "$NS_PATH" ] && continue + MANIFEST_DIR=$(dirname "$MANIFEST") + + echo "Manifest: \`${MANIFEST}\` → namespace \`${NS_PATH}\`" >> $GITHUB_STEP_SUMMARY + + # Check PHP files have matching namespace + while IFS= read -r -d '' PHP_FILE; do + FILE_NS=$(grep -oP '^\s*namespace\s+\K[^;]+' "$PHP_FILE" 2>/dev/null | head -1) + [ -z "$FILE_NS" ] && continue + + # Namespace should start with the manifest namespace path + if ! echo "$FILE_NS" | grep -qF "${NS_PATH}"; then + echo "- \`${PHP_FILE}\`: namespace \`${FILE_NS}\` doesn't match manifest \`${NS_PATH}\`" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done < <(find "$MANIFEST_DIR" -name "*.php" -path "*/src/*" -not -path "./vendor/*" -print0 2>/dev/null) + done + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} namespace mismatch(es).**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Namespace consistency check passed.**" >> $GITHUB_STEP_SUMMARY + fi + + - name: SPDX license header check + continue-on-error: true + run: | + echo "### SPDX License Headers" >> $GITHUB_STEP_SUMMARY + MISSING=0 + + SRC_DIR="" + for DIR in source/ src/ htdocs/; do + [ -d "$DIR" ] && SRC_DIR="$DIR" && break + done + + if [ -z "$SRC_DIR" ]; then + echo "No source directory found — skipping." >> $GITHUB_STEP_SUMMARY + else + TOTAL=0 + while IFS= read -r -d '' FILE; do + TOTAL=$((TOTAL + 1)) + if ! head -10 "$FILE" | grep -qi "SPDX"; then + echo "- Missing SPDX header: \`${FILE}\`" >> $GITHUB_STEP_SUMMARY + MISSING=$((MISSING + 1)) + fi + done < <(find "$SRC_DIR" -name "*.php" -not -path "./vendor/*" -print0) + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "$MISSING" -gt 0 ]; then + echo "**${MISSING}/${TOTAL} PHP file(s) missing SPDX license header.**" >> $GITHUB_STEP_SUMMARY + else + echo "**All ${TOTAL} PHP files have SPDX headers.**" >> $GITHUB_STEP_SUMMARY + fi + fi + + - name: Service provider check + run: | + echo "### Service Provider Check" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + PROVIDERS=$(find . -name "provider.php" -path "*/services/*" -not -path "./.git/*" -not -path "./vendor/*" 2>/dev/null) + if [ -z "$PROVIDERS" ]; then + echo "No service providers found — skipping." >> $GITHUB_STEP_SUMMARY + else + for FILE in $PROVIDERS; do + # Must return a ServiceProviderInterface + if ! grep -qP 'ServiceProviderInterface|ComponentInterface|MVCFactoryInterface|DispatcherInterface' "$FILE" 2>/dev/null; then + echo "- \`${FILE}\`: does not reference ServiceProviderInterface or component interfaces" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "- \`${FILE}\`: valid service provider" >> $GITHUB_STEP_SUMMARY + fi + + # Must have return statement + if ! grep -qP '^\s*return\s+new\s+' "$FILE" 2>/dev/null; then + echo "- \`${FILE}\`: missing \`return new ...\` statement" >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + done + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${ERRORS}" -gt 0 ]; then + echo "**${ERRORS} service provider issue(s).**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Service provider check passed.**" >> $GITHUB_STEP_SUMMARY + fi + + release-readiness: + name: Release Readiness Check + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.base_ref == 'main' + continue-on-error: true + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate release readiness + run: | + echo "## Release Readiness" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + ERRORS=0 + + # Extract version from README.md + README_VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1) + if [ -z "$README_VERSION" ]; then + echo "No VERSION found in README.md FILE INFORMATION block." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "README version: \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY + fi + + # Find the extension manifest + MANIFEST="" + for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do + if grep -q "/dev/null; then + MANIFEST="$XML_FILE" + break + fi + done + + if [ -z "$MANIFEST" ]; then + echo "No Joomla extension manifest found." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Manifest: \`${MANIFEST}\`" >> $GITHUB_STEP_SUMMARY + + # Check matches README VERSION + MANIFEST_VERSION=$(grep -oP '\K[^<]+' "$MANIFEST" | head -1) + if [ -z "$MANIFEST_VERSION" ]; then + echo "No \`\` tag in manifest." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + elif [ -n "$README_VERSION" ] && [ "$MANIFEST_VERSION" != "$README_VERSION" ]; then + echo "Manifest version \`${MANIFEST_VERSION}\` does not match README \`${README_VERSION}\`." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Manifest version: \`${MANIFEST_VERSION}\`" >> $GITHUB_STEP_SUMMARY + fi + + # Check extension type, element, client attributes + EXT_TYPE=$(grep -oP ']*\btype="\K[^"]+' "$MANIFEST" | head -1) + if [ -z "$EXT_TYPE" ]; then + echo "Missing \`type\` attribute on \`\` tag." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + else + echo "Extension type: \`${EXT_TYPE}\`" >> $GITHUB_STEP_SUMMARY + fi + + # Element check (component/module/plugin name) + HAS_ELEMENT=$(grep -cP '<(element|name)>' "$MANIFEST" 2>/dev/null || echo "0") + if [ "$HAS_ELEMENT" -eq 0 ]; then + echo "Missing \`\` or \`\` in manifest." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + + # Client attribute for site/admin modules and plugins + if echo "$EXT_TYPE" | grep -qP "^(module|plugin)$"; then + HAS_CLIENT=$(grep -cP ']*\bclient=' "$MANIFEST" 2>/dev/null || echo "0") + if [ "$HAS_CLIENT" -eq 0 ]; then + echo "Missing \`client\` attribute for ${EXT_TYPE} extension." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + fi + fi + + # Check updates.xml exists + if [ -f "updates.xml" ] || [ -f "updates.xml" ]; then + echo "Update XML present." >> $GITHUB_STEP_SUMMARY + else + echo "No updates.xml found." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + + # Check CHANGELOG.md exists + if [ -f "CHANGELOG.md" ]; then + echo "CHANGELOG.md present." >> $GITHUB_STEP_SUMMARY + else + echo "No CHANGELOG.md found." >> $GITHUB_STEP_SUMMARY + ERRORS=$((ERRORS + 1)) + fi + + echo "" >> $GITHUB_STEP_SUMMARY + if [ $ERRORS -gt 0 ]; then + echo "**${ERRORS} issue(s) must be resolved before release.**" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "**Extension is ready for release.**" >> $GITHUB_STEP_SUMMARY + fi + + test: + name: Tests (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + needs: lint-and-validate + + strategy: + fail-fast: false + matrix: + php: ['8.2', '8.3'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup PHP ${{ matrix.php }} + run: | + if ! command -v php &> /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 + php -v && composer --version + + - name: Install dependencies + env: + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || secrets.GA_TOKEN || github.token }}"}}' + run: | + if [ -f "composer.json" ]; then + composer install \ + --no-interaction \ + --prefer-dist \ + --optimize-autoloader + else + echo "No composer.json found — skipping dependency install" + fi + + - name: Run tests + run: | + echo "### Test Results (PHP ${{ matrix.php }})" >> $GITHUB_STEP_SUMMARY + if [ -f "phpunit.xml" ] || [ -f "phpunit.xml.dist" ]; then + vendor/bin/phpunit --testdox 2>&1 | tee /tmp/test-output.log + EXIT=${PIPESTATUS[0]} + if [ $EXIT -eq 0 ]; then + echo "All tests passed." >> $GITHUB_STEP_SUMMARY + else + echo "Test failures detected — see log." >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat /tmp/test-output.log >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + fi + exit $EXIT + else + echo "No phpunit.xml found — skipping tests." >> $GITHUB_STEP_SUMMARY + fi + + static-analysis: + name: PHPStan Analysis + runs-on: ubuntu-latest + needs: lint-and-validate + continue-on-error: true + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup PHP + run: | + if ! command -v php &> /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 + php -v && composer --version + + - name: Install dependencies + env: + COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || secrets.GA_TOKEN || github.token }}"}}' + run: | + if [ -f "composer.json" ]; then + composer install --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Install PHPStan + run: | + if ! command -v vendor/bin/phpstan &> /dev/null; then + composer require --dev phpstan/phpstan --no-interaction 2>/dev/null || \ + composer global require phpstan/phpstan --no-interaction + fi + + - name: Run PHPStan + run: | + echo "### PHPStan Static Analysis" >> $GITHUB_STEP_SUMMARY + PHPSTAN="vendor/bin/phpstan" + if [ ! -f "$PHPSTAN" ]; then + PHPSTAN=$(composer global config bin-dir --absolute 2>/dev/null)/phpstan + fi + + # Determine source directory + SRC_DIR="" + for DIR in src/ htdocs/ lib/; do + if [ -d "$DIR" ]; then + SRC_DIR="$DIR" + break + fi + done + + if [ -z "$SRC_DIR" ]; then + echo "No source directory found (src/, htdocs/, lib/) — skipping." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + # Use repo phpstan.neon if present, otherwise use baseline config + ARGS="analyse ${SRC_DIR} --memory-limit=512M --no-progress --error-format=table" + if [ -f "phpstan.neon" ] || [ -f "phpstan.neon.dist" ]; then + echo "Using project PHPStan config." >> $GITHUB_STEP_SUMMARY + else + ARGS="$ARGS --level=3" + echo "No phpstan.neon found — using level 3 (type inference)." >> $GITHUB_STEP_SUMMARY + fi + + $PHPSTAN $ARGS 2>&1 | tee /tmp/phpstan-output.txt + EXIT=${PIPESTATUS[0]} + + if [ $EXIT -eq 0 ]; then + echo "**No errors found.**" >> $GITHUB_STEP_SUMMARY + else + ERRORS=$(grep -c "ERROR" /tmp/phpstan-output.txt 2>/dev/null || echo "some") + echo "**${ERRORS} error(s) found.** Review output above." >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + tail -30 /tmp/phpstan-output.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + fi + exit $EXIT + + pre-release: + name: Build RC Pre-Release + runs-on: ubuntu-latest + needs: [lint-and-validate, test] + if: github.event_name == 'pull_request' + + steps: + - name: Trigger pre-release build + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + REPO: ${{ github.repository }} + BRANCH: ${{ github.head_ref }} + run: | + curl -s -X POST \ + "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" \ + -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}" + echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY + echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY diff --git a/.mokogitea/workflows/composer-publish.yml b/.mokogitea/workflows/composer-publish.yml deleted file mode 100644 index 03735c9..0000000 --- a/.mokogitea/workflows/composer-publish.yml +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# SPDX-License-Identifier: GPL-3.0-or-later - -name: "Publish to Composer" - -on: - push: - tags: - - 'v*' - - '[0-9]*.[0-9]*.[0-9]*' - release: - types: [published] - workflow_dispatch: - -env: - GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - -jobs: - publish: - name: Publish Package - runs-on: ubuntu-latest - if: >- - !contains(github.event.head_commit.message, '[skip ci]') && - !contains(github.event.head_commit.message, '[skip publish]') - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP - run: | - if ! command -v php &> /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 - - - name: Install dependencies - run: composer install --no-dev --no-interaction --prefer-dist --quiet - - - name: Determine version - id: version - run: | - VERSION=$(php -r "echo json_decode(file_get_contents('composer.json'))->version;") - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - echo "Package version: ${VERSION}" - - # Gitea Composer Registry — auto-publishes from tags - # The tag push itself registers the package at: - # https://git.mokoconsulting.tech/api/packages/MokoConsulting/composer - - name: Verify Gitea registry - run: | - echo "Gitea Composer registry auto-publishes from tags." - echo "Package available at: ${GITEA_URL}/api/packages/MokoConsulting/composer" - echo "Install: composer require mokoconsulting/mokocli" - - # Packagist — notify of new version - - name: Notify Packagist - if: secrets.PACKAGIST_TOKEN != '' - run: | - VERSION="${{ steps.version.outputs.version }}" - echo "Notifying Packagist of version ${VERSION}..." - curl -sf -X POST \ - -H "Content-Type: application/json" \ - -d '{"repository":{"url":"https://git.mokoconsulting.tech/MokoConsulting/mokocli"}}' \ - "https://packagist.org/api/update-package?username=mokoconsulting&apiToken=${{ secrets.PACKAGIST_TOKEN }}" \ - && echo "Packagist notified" \ - || echo "::warning::Packagist notification failed (package may not be registered yet)" - - - name: Summary - run: | - VERSION="${{ steps.version.outputs.version }}" - echo "## Composer Package Published" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Registry | Status |" >> $GITHUB_STEP_SUMMARY - echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY - echo "| Gitea | \`composer require mokoconsulting/mokocli:${VERSION}\` |" >> $GITHUB_STEP_SUMMARY - echo "| Packagist | \`composer require mokoconsulting/mokocli\` |" >> $GITHUB_STEP_SUMMARY diff --git a/.mokogitea/workflows/deploy-manual.yml b/.mokogitea/workflows/deploy-manual.yml deleted file mode 100644 index bb133ed..0000000 --- a/.mokogitea/workflows/deploy-manual.yml +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Deploy -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API -# PATH: /templates/workflows/joomla/deploy-manual.yml.template -# VERSION: 04.07.00 -# BRIEF: Manual SFTP deploy to dev server for Joomla repos - -name: "Universal: Deploy to Dev (Manual)" - -on: - workflow_dispatch: - inputs: - clear_remote: - description: 'Delete all remote files before uploading' - required: false - default: 'false' - type: boolean - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -permissions: - contents: read - -jobs: - deploy: - name: SFTP Deploy to Dev - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - - name: Setup PHP - run: | - php -v && composer --version - - - name: Setup MokoStandards tools - env: - GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }} - MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }} - MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }} - COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}' - run: | - git clone --depth 1 --branch main --quiet \ - "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \ - /tmp/mokostandards-api 2>/dev/null || true - if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then - cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true - fi - - - name: Check FTP configuration - id: check - env: - HOST: ${{ vars.DEV_FTP_HOST }} - PATH_VAR: ${{ vars.DEV_FTP_PATH }} - PORT: ${{ vars.DEV_FTP_PORT }} - run: | - if [ -z "$HOST" ] || [ -z "$PATH_VAR" ]; then - echo "DEV_FTP_HOST or DEV_FTP_PATH not configured -- cannot deploy" - echo "skip=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - echo "skip=false" >> "$GITHUB_OUTPUT" - echo "host=$HOST" >> "$GITHUB_OUTPUT" - - REMOTE="${PATH_VAR%/}" - echo "remote=$REMOTE" >> "$GITHUB_OUTPUT" - - [ -z "$PORT" ] && PORT="22" - echo "port=$PORT" >> "$GITHUB_OUTPUT" - - - name: Deploy via SFTP - if: steps.check.outputs.skip != 'true' - env: - SFTP_KEY: ${{ secrets.DEV_FTP_KEY }} - SFTP_PASS: ${{ secrets.DEV_FTP_PASSWORD }} - SFTP_USER: ${{ vars.DEV_FTP_USERNAME }} - run: | - SOURCE_DIR="src" - [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs" - [ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ -- nothing to deploy"; exit 0; } - - printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \ - "${{ steps.check.outputs.host }}" "${{ steps.check.outputs.port }}" "$SFTP_USER" "${{ steps.check.outputs.remote }}" \ - > /tmp/sftp-config.json - - if [ -n "$SFTP_KEY" ]; then - echo "$SFTP_KEY" > /tmp/deploy_key - chmod 600 /tmp/deploy_key - printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json - else - printf ',"password":"%s"}' "$SFTP_PASS" >> /tmp/sftp-config.json - fi - - DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json) - [ "${{ inputs.clear_remote }}" = "true" ] && DEPLOY_ARGS+=(--clear-remote) - - PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true) - if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then - php /tmp/mokostandards-api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}" - else - php /tmp/mokostandards-api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}" - fi - - rm -f /tmp/deploy_key /tmp/sftp-config.json - - - name: Summary - if: always() - run: | - if [ "${{ steps.check.outputs.skip }}" = "true" ]; then - echo "### Deploy Skipped -- FTP not configured" >> $GITHUB_STEP_SUMMARY - else - echo "### Manual Dev Deploy Complete" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY - echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| Host | \`${{ steps.check.outputs.host }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| Remote | \`${{ steps.check.outputs.remote }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| Clear | ${{ inputs.clear_remote }} |" >> $GITHUB_STEP_SUMMARY - fi diff --git a/.mokogitea/workflows/pr-metadata-check.yml b/.mokogitea/workflows/pr-metadata-check.yml new file mode 100644 index 0000000..68b7589 --- /dev/null +++ b/.mokogitea/workflows/pr-metadata-check.yml @@ -0,0 +1,71 @@ +# Copyright (C) 2026 Moko Consulting +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: mokocli.Validation +# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli +# PATH: /templates/workflows/joomla/pr-metadata-check.yml.template +# VERSION: 01.00.00 +# BRIEF: Validate MokoGitea metadata matches Joomla extension manifest on PRs + +name: "Joomla: Metadata Validation" + +on: + pull_request: + types: [opened, synchronize, reopened, converted_to_draft, ready_for_review] + +permissions: + contents: read + +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: + validate-metadata: + name: "Validate Joomla Metadata" + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup mokocli tools + env: + MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting + run: | + if [ -f /opt/mokocli/cli/joomla_metadata_validate.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then + echo Using pre-installed /opt/mokocli + echo MOKO_CLI=/opt/mokocli/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/mokocli + CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git + git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli + cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet + echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV + fi + + - name: Validate metadata against Joomla manifest + env: + GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + run: | + php ${MOKO_CLI}/joomla_metadata_validate.php \ + --path . \ + --token "${GITEA_TOKEN}" \ + --org "${GITEA_ORG}" \ + --repo "${GITEA_REPO}" \ + --api-base "${GITEA_URL}/api/v1" \ + --ci + + if [ $? -ne 0 ]; then + echo "::error::Joomla metadata mismatch — update delivery will fail. Run 'php cli/joomla_metadata_validate.php' locally to see details." + exit 1 + fi From 22cf1aab38270846083e6e756d5025655f7b6b1b Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 12:44:41 +0000 Subject: [PATCH 08/59] chore(version): auto-bump patch 01.07.05-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index c9afddc..244aec3 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.04 +# VERSION: 01.07.05 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 18a175d..08102d3 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.04 + 01.07.05 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 2494ee6..18e0f54 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.04 + 01.07.05 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 4a570e54c91d4005f4a325f9bbb623f68058c837 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 12:44:58 +0000 Subject: [PATCH 09/59] chore(version): pre-release bump to 01.07.06-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 244aec3..ff40ad2 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.05 +# VERSION: 01.07.06 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 08102d3..125ce8e 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.05 + 01.07.06 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 18e0f54..fe04033 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.05 + 01.07.06 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 95c3bbf8c590d4b228a63c03497e3d2ebdda346b Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 23 Jun 2026 12:40:54 -0500 Subject: [PATCH 10/59] =?UTF-8?q?chore:=20remove=20static=20updates.xml=20?= =?UTF-8?q?=E2=80=94=20MokoGitea=20generates=20dynamically?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/updates.xml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 source/updates.xml diff --git a/source/updates.xml b/source/updates.xml deleted file mode 100644 index 9d8cdc8..0000000 --- a/source/updates.xml +++ /dev/null @@ -1,9 +0,0 @@ - - -Package - MokoSuite NPO -pkg_mokosuitenpo -package -01.01.00 - -8.3 - From 71ee3afceb01cb456fc9a1de23f48da12b3d0d20 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 17:42:16 +0000 Subject: [PATCH 11/59] chore(version): auto-bump patch 01.07.07-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index ff40ad2..268b333 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.06 +# VERSION: 01.07.07 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 125ce8e..2c29494 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.06 + 01.07.07 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index fe04033..530faab 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.06 + 01.07.07 2026-06-11 Moko Consulting hello@mokoconsulting.tech From a02c7e3e582f776f83dd79e230415bfd6981f763 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 17:42:30 +0000 Subject: [PATCH 12/59] chore(version): pre-release bump to 01.07.08-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 268b333..f0015a2 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.07 +# VERSION: 01.07.08 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 2c29494..e428b04 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.07 + 01.07.08 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 530faab..6115b86 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.07 + 01.07.08 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 4c3479e822ed807652709a1c133d087cadf6202f Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Tue, 23 Jun 2026 18:05:37 +0000 Subject: [PATCH 13/59] chore: remove security-audit.yml -- handled by MokoGitea --- .mokogitea/workflows/security-audit.yml | 82 ------------------------- 1 file changed, 82 deletions(-) delete mode 100644 .mokogitea/workflows/security-audit.yml diff --git a/.mokogitea/workflows/security-audit.yml b/.mokogitea/workflows/security-audit.yml deleted file mode 100644 index 789325a..0000000 --- a/.mokogitea/workflows/security-audit.yml +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Gitea.Workflow -# INGROUP: MokoStandards.Security -# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards -# PATH: /.gitea/workflows/security-audit.yml -# VERSION: 01.00.00 -# BRIEF: Dependency vulnerability scanning for composer and npm packages - -name: "Universal: Security Audit" - -on: - schedule: - - cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC - pull_request: - branches: - - main - paths: - - 'composer.json' - - 'composer.lock' - - 'package.json' - - 'package-lock.json' - workflow_dispatch: - -permissions: - contents: read - -env: - NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }} - NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }} - -jobs: - audit: - name: Dependency Audit - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Composer audit - if: hashFiles('composer.lock') != '' - run: | - echo "=== Composer Security Audit ===" - if ! command -v composer &> /dev/null; then - sudo apt-get update -qq - sudo apt-get install -y -qq php-cli composer >/dev/null 2>&1 - fi - composer audit --format=plain 2>&1 | tee /tmp/composer-audit.txt - RESULT=$? - if [ $RESULT -ne 0 ]; then - echo "::warning::Composer vulnerabilities found" - echo "composer_vulnerable=true" >> "$GITHUB_ENV" - else - echo "No known vulnerabilities in composer dependencies" - fi - - - name: NPM audit - if: hashFiles('package-lock.json') != '' - run: | - echo "=== NPM Security Audit ===" - npm audit --production 2>&1 | tee /tmp/npm-audit.txt || true - if npm audit --production 2>&1 | grep -q "found 0 vulnerabilities"; then - echo "No known vulnerabilities in npm dependencies" - else - echo "::warning::NPM vulnerabilities found" - echo "npm_vulnerable=true" >> "$GITHUB_ENV" - fi - - - name: Notify on vulnerabilities - if: env.composer_vulnerable == 'true' || env.npm_vulnerable == 'true' - run: | - REPO="${{ github.event.repository.name }}" - curl -sS \ - -H "Title: ${REPO} has vulnerable dependencies" \ - -H "Tags: lock,warning" \ - -H "Priority: high" \ - -d "Security audit found vulnerabilities. Review dependency updates." \ - "${NTFY_URL}/${NTFY_TOPIC}" || true From 303d0c7b6a1f1a04b052bc1fde1622ea034196da Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 18:26:56 +0000 Subject: [PATCH 14/59] chore(version): auto-bump patch 01.07.09-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index f0015a2..0e3d0ee 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.08 +# VERSION: 01.07.09 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index e428b04..fca6195 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.08 + 01.07.09 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 6115b86..a97bf85 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.08 + 01.07.09 2026-06-11 Moko Consulting hello@mokoconsulting.tech From ebe419852f374029144510ea83b85d8cb247f606 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 23 Jun 2026 18:27:29 +0000 Subject: [PATCH 15/59] chore(version): pre-release bump to 01.07.10-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 0e3d0ee..157d24d 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.09 +# VERSION: 01.07.10 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index fca6195..7c345db 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.09 + 01.07.10 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index a97bf85..a3b8fbe 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.09 + 01.07.10 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 51afb62d8c90a6704987f24700f1d9e0e268b4ea Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Wed, 24 Jun 2026 12:17:37 +0000 Subject: [PATCH 16/59] chore(version): pre-release bump to 01.07.11-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 157d24d..448c4d0 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.10 +# VERSION: 01.07.11 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 7c345db..dcbedec 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.10 + 01.07.11 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index a3b8fbe..f8def12 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.10 + 01.07.11 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 8e99096941e041e396be431bee85ec080135d340 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:10:03 +0000 Subject: [PATCH 17/59] chore: add .editorconfig from Template-Joomla --- .editorconfig | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..09975f7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,31 @@ +# EditorConfig https://editorconfig.org +root = true + +[*] +indent_style = tab +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.ps1] +end_of_line = crlf + +[*.md] +trim_trailing_whitespace = false + +[*.{json,yml,yaml}] +indent_style = space +indent_size = 2 + +[*.{mak,Makefile}] +indent_style = tab + +[*.bat] +end_of_line = crlf + +[*.sh] +end_of_line = lf +indent_style = space +indent_size = 2 From cbdb35a76d6b507509e94d5866af6ed5547e5234 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:10:40 +0000 Subject: [PATCH 18/59] chore: add composer.json from Template-Joomla --- composer.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d938818 --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "mokoconsulting/mokojoomgallery", + "description": "Joomla extension by Moko Consulting", + "type": "joomla-package", + "license": "GPL-3.0-or-later", + "homepage": "https://mokoconsulting.tech", + "authors": [ + { + "name": "Moko Consulting", + "email": "hello@mokoconsulting.tech" + } + ], + "require": { + "php": ">=8.1" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.0", + "phpstan/phpstan": "^2.0", + "joomla/coding-standards": "dev-main" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} From d143275f303f636128c5df282ef418d37143d37d Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:11:04 +0000 Subject: [PATCH 19/59] chore: add phpstan.neon from Template-Joomla --- phpstan.neon | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 phpstan.neon diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..d6e669c --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,20 @@ +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# FILE INFORMATION +# DEFGROUP: Config.StaticAnalysis +# INGROUP: Development +# BRIEF: PHPStan configuration for Joomla extension static analysis + +parameters: + level: 5 + paths: + - src + scanDirectories: + # Joomla framework stubs (if available) + - vendor/joomla + ignoreErrors: + # Joomla service-container architecture: Factory/Container returns mixed + - '#Call to an undefined method Joomla\\CMS\\Application\\.*::get#i' + - '#Call to method .* on an unknown class Joomla\\Cms\\Extension\\.*#' + # Joomla MVC pattern: Table::getInstance returns Table|bool + - '#Method Joomla\\CMS\\Table\\Table::getInstance#' From 99f71d0d5f16fb092edb57e7774a402ebd81ca69 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:11:41 +0000 Subject: [PATCH 20/59] chore: add CODE_OF_CONDUCT.md from Template-Joomla --- CODE_OF_CONDUCT.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2ecc653 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,35 @@ + + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, colour, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behaviour that contributes to a positive environment: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Accepting constructive criticism gracefully +- Focusing on what is best for the community + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behaviour may be +reported by contacting the project team at +[info@mokoconsulting.tech](mailto:info@mokoconsulting.tech). + +## Attribution + +This Code of Conduct is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org), version 2.1. From dc457e6744e27dcf6cf5910e5444d751deadbe61 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:13:39 +0000 Subject: [PATCH 21/59] chore: add CONTRIBUTING.md from Template-Joomla --- CONTRIBUTING.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e8697d2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,88 @@ + + +# Contributing to Moko Consulting Projects + +Thank you for your interest in contributing! This guide explains our workflow, +conventions, and how to get your changes merged. + +## Branching Workflow + +We use a **stability-gated** branching model: + +``` +feature/* ──── PR ───→ dev + │ RC cut → rc → main +fix/* ───────── PR ────────────┘ +``` + +1. **Create a branch** from `dev`: + - `feature/` for new functionality + - `fix/` for bug fixes + - `chore/` for maintenance +2. **Open a PR** into `dev`. +3. **CI must pass** before merge. +4. **Release cuts**: `dev → rc → main` are handled by maintainers. + +> **Never commit directly to `main` or `dev`.** + +## Version Policy + +All repositories use the **XX.YY.ZZ** versioning scheme (two-digit segments): + +- `XX` -- major (breaking changes) +- `YY` -- minor (new features, backward-compatible) +- `ZZ` -- patch (bug fixes, security patches) + +**Stability suffixes** may be appended during pre-release: + +| Suffix | Meaning | Example | +|---|---|---| +| `-alpha.N` | Early testing | `06.01.00-alpha.1` | +| `-beta.N` | Feature complete | `06.01.00-beta.2` | +| `-rc.N` | Release candidate | `06.01.00-rc.1` | +| *(none)* | Stable release | `06.01.00` | + +## Auto-Bump + +Version bumps are **automated** via the `auto-bump` workflow: + +- Merges into `dev` trigger a minor/patch bump. +- The workflow updates all version references (manifests, changelog, etc.). +- **Do not manually edit version numbers** -- let the workflow handle it. + +## Commit Messages + +We follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +(): + + + + +``` + +**Types**: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`, `revert` + +## Pull Request Checklist + +Before submitting a PR, ensure: + +- [ ] Branch is based on latest `dev` +- [ ] Commit messages follow conventional commits +- [ ] CHANGELOG.md updated under `[Unreleased]` +- [ ] No `TODO.md`, `.claude/`, `.mcp.json`, or minified files included +- [ ] Code follows [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards) +- [ ] All CI checks pass + +## Code of Conduct + +All contributors are expected to follow our [Code of Conduct](CODE_OF_CONDUCT.md). + +## Questions? + +Open a [Question issue](../../issues/new?template=question.md) or contact +us at [hello@mokoconsulting.tech](mailto:hello@mokoconsulting.tech). From 7b75aa239c681d6ea92e02096550134b63647820 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:15:08 +0000 Subject: [PATCH 22/59] chore: add GOVERNANCE.md from Template-Joomla --- GOVERNANCE.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 GOVERNANCE.md diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..aeb3e4b --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,49 @@ + + +# Governance + +## Project Leadership + +This repository is maintained by **Moko Consulting** under a **sole operator** model. + +- **Lead Maintainer**: Jonathan Miller (@jmiller) +- **Organisation**: [Moko Consulting](https://mokoconsulting.tech) + +## Decision Making + +- All architectural decisions are made by the lead maintainer. +- Community feedback is welcome via [RFC issues](../../issues/new?template=rfc.md). +- Breaking changes are documented via [ADR issues](../../issues/new?template=adr.md). + +## Contribution Policy + +- **All changes** must go through a pull request (PR). +- **CI checks** are mandatory before merge. +- **Direct push** to `main` and `dev` is restricted to automated workflows. + +## Code of Conduct + +All participants must adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). + +## Licensing + +All contributions are licensed under the same license as the project +(GPL-3.0-or-later unless otherwise stated in the repository root). + +## Security + +Security vulnerabilities should be reported privately. +See [SECURITY.md](SECURITY.md) for details. + +## Dispute Resolution + +Disputes are resolved by the lead maintainer. For escalation, +contact [info@mokoconsulting.tech](mailto:info@mokoconsulting.tech). + +## Changes to Governance + +This document may be updated at any time by the lead maintainer. +Significant changes will be announced via an RFC issue. From ed90019f7965dd0600ab066ef8ee47a2e38b8302 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:15:26 +0000 Subject: [PATCH 23/59] chore(version): pre-release bump to 01.07.12-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 448c4d0..e4229b2 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.11 +# VERSION: 01.07.12 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index dcbedec..a2f899b 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.11 + 01.07.12 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index f8def12..0cfbe73 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.11 + 01.07.12 2026-06-11 Moko Consulting hello@mokoconsulting.tech From ac4acd81ac5f66b57b7abed93409986a1eba9107 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:15:32 +0000 Subject: [PATCH 24/59] chore: add SECURITY.md from Template-Joomla --- SECURITY.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7f29d29 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,90 @@ + + +# Security Policy + +## Supported Versions + +| Version | Supported | +|---|---| +| Latest stable | ✅ Full support | +| Previous major | ⚠️ Critical fixes only | +| Older | ❌ No support | + +## Reporting a Vulnerability + +**Do not report security vulnerabilities via public issues.** + +Instead, please report them privately: + +1. **Email**: [security@mokoconsulting.tech](mailto:security@mokoconsulting.tech) +2. **Subject**: `[SECURITY] - ` + +### What to Include + +- Description of the vulnerability +- Steps to reproduce +- Affected versions +- Potential impact +- Suggested fix (if any) + +## Severity Classification + +| Severity | Description | Response Time | +|---|---|---| +| **Critical** | Remote code execution, SQL injection, auth bypass | 24 hours | +| **High** | XSS, CSRF, privilege escalation | 48 hours | +| **Medium** | Information disclosure, path traversal | 72 hours | +| **Low** | Best practice violation, hardening suggestion | Next release | + +## Remediation Timeline + +1. **Acknowledgement**: Within 24 hours of report +2. **Assessment**: Within 72 hours +3. **Fix development**: Based on severity +4. **Release**: Patch release with security advisory +5. **Disclosure**: Coordinated disclosure after fix is available + +## Security Best Practices + +### For Contributors + +- Never commit secrets, credentials, or API keys +- Use parameterised queries (no raw SQL concatenation) +- Validate and sanitise all user input +- Follow Joomla API for access control checks +- Use Joomla's `HTMLHelper` for output escaping +- Include SPDX license headers in all source files + +### For Users + +- Keep Joomla and all extensions updated +- Use strong, unique passwords +- Enable two-factor authentication +- Review file permissions regularly +- Monitor Joomla error logs + +## Security Updates + +Security patches are delivered through the standard update channel. +Critical fixes may receive an emergency out-of-band release. + +## Responsible Disclosure + +We follow coordinated disclosure practices: + +- We will work with reporters to understand and reproduce the issue +- We will develop and test a fix +- We will credit reporters (with permission) in security advisories +- We ask that reporters allow reasonable time for a fix before public disclosure + +## Contact + +- **Security team**: [security@mokoconsulting.tech](mailto:security@mokoconsulting.tech) +- **General**: [hello@mokoconsulting.tech](mailto:hello@mokoconsulting.tech) + +--- + +Thank you for helping keep Moko Consulting projects secure. From 1a71d4d413f76280438a1728c2207b15004c327b Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:17:30 +0000 Subject: [PATCH 25/59] chore: add issue templates from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/bug_report.md | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/bug_report.md diff --git a/.mokogitea/ISSUE_TEMPLATE/bug_report.md b/.mokogitea/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..38a16a7 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,48 @@ +--- +name: Bug Report +about: Report a bug or issue with the project +title: '[BUG] ' +labels: 'bug' +assignees: '' + +--- + + +## Bug Description +A clear and concise description of what the bug is. + +## Steps to Reproduce +1. Go to '...' +2. Click on '...' +3. Scroll down to '...' +4. See error + +## Expected Behavior +A clear and concise description of what you expected to happen. + +## Actual Behavior +A clear and concise description of what actually happened. + +## Screenshots +If applicable, add screenshots to help explain your problem. + +## Environment +- **Project**: [e.g., MokoDoliTools, moko-cassiopeia] +- **Version**: [e.g., 1.2.3] +- **Platform**: [e.g., Dolibarr 18.0, Joomla 5.0] +- **PHP Version**: [e.g., 8.1] +- **Database**: [e.g., MySQL 8.0, PostgreSQL 14] +- **Browser** (if applicable): [e.g., Chrome 120, Firefox 121] +- **OS**: [e.g., Ubuntu 22.04, Windows 11] + +## Additional Context +Add any other context about the problem here. + +## Possible Solution +If you have suggestions on how to fix the issue, please describe them here. + +## Checklist +- [ ] I have searched for similar issues before creating this one +- [ ] I have provided all the requested information +- [ ] I have tested this on the latest stable version +- [ ] I have checked the documentation and couldn't find a solution From ac8f53327b39cfc96df8d74d628acb05255a4c07 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:17:57 +0000 Subject: [PATCH 26/59] chore: add feature_request template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/feature_request.md | 51 ++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/feature_request.md diff --git a/.mokogitea/ISSUE_TEMPLATE/feature_request.md b/.mokogitea/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7b76dc9 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,51 @@ +--- +name: Feature Request +about: Suggest a new feature or enhancement +title: '[FEATURE] ' +labels: 'enhancement' +assignees: '' + +--- + + +## Feature Description +A clear and concise description of the feature you'd like to see. + +## Problem or Use Case +Describe the problem this feature would solve or the use case it addresses. +Ex. I'm always frustrated when [...] + +## Proposed Solution +A clear and concise description of what you want to happen. + +## Alternative Solutions +A clear and concise description of any alternative solutions or features you've considered. + +## Benefits +Describe how this feature would benefit users: +- Who would use this feature? +- What problems does it solve? +- What value does it add? + +## Implementation Details (Optional) +If you have ideas about how this could be implemented, share them here: +- Technical approach +- Files/components that might need changes +- Any concerns or challenges you foresee + +## Additional Context +Add any other context, mockups, or screenshots about the feature request here. + +## Relevant Standards +Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +- [ ] Accessibility (WCAG 2.1 AA) +- [ ] Localization (en_US/en_GB) +- [ ] Security best practices +- [ ] Code quality standards +- [ ] Other: [specify] + +## Checklist +- [ ] I have searched for similar feature requests before creating this one +- [ ] I have clearly described the use case and benefits +- [ ] I have considered alternative solutions +- [ ] This feature aligns with the project's goals and scope From 2faefb413841fc90c7c56fb81d9b785a19f8b4fc Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:19:10 +0000 Subject: [PATCH 27/59] chore: add issue template config from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/config.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/config.yml diff --git a/.mokogitea/ISSUE_TEMPLATE/config.yml b/.mokogitea/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..d4d49ec --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,18 @@ +--- +blank_issues_enabled: true +contact_links: + - name: 💼 Enterprise Support + url: https://mokoconsulting.tech/enterprise + about: Enterprise-level support and consultation services + - name: 💬 Ask a Question + url: https://mokoconsulting.tech/ + about: Get help or ask questions through our website + - name: 📚 MokoStandards Documentation + url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform + about: View our coding standards and best practices + - name: 🔒 Report a Security Vulnerability + url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new + about: Report security vulnerabilities privately (for critical issues) + - name: 💡 Community Discussions + url: https://github.com/orgs/mokoconsulting-tech/discussions + about: Join community discussions and Q&A From 9082563055e1f90a04492d2700bc5f46e3f006b5 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:19:23 +0000 Subject: [PATCH 28/59] chore: add joomla_issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/joomla_issue.md | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/joomla_issue.md diff --git a/.mokogitea/ISSUE_TEMPLATE/joomla_issue.md b/.mokogitea/ISSUE_TEMPLATE/joomla_issue.md new file mode 100644 index 0000000..d808f79 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/joomla_issue.md @@ -0,0 +1,87 @@ +--- +name: Joomla Extension Issue +about: Report an issue with a Joomla extension +title: '[JOOMLA] ' +labels: 'joomla' +assignees: '' + +--- + + +## Issue Type +- [ ] Component Issue +- [ ] Module Issue +- [ ] Plugin Issue +- [ ] Template Issue + +## Extension Details +- **Extension Name**: [e.g., moko-cassiopeia] +- **Extension Version**: [e.g., 1.2.3] +- **Extension Type**: [Component / Module / Plugin / Template] + +## Joomla Environment +- **Joomla Version**: [e.g., 4.4.0, 5.0.0] +- **PHP Version**: [e.g., 8.1.0] +- **Database**: [MySQL / PostgreSQL / MariaDB] +- **Database Version**: [e.g., 8.0] +- **Server**: [Apache / Nginx / IIS] +- **Hosting**: [Shared / VPS / Dedicated / Cloud] + +## Issue Description +Provide a clear and detailed description of the issue. + +## Steps to Reproduce +1. Go to '...' +2. Click on '...' +3. Configure '...' +4. See error + +## Expected Behavior +What you expected to happen. + +## Actual Behavior +What actually happened. + +## Error Messages +``` +# Paste any error messages from Joomla error logs +# Location: administrator/logs/error.php +``` + +## Browser Console Errors +```javascript +// Paste any JavaScript console errors (F12 in browser) +``` + +## Screenshots +Add screenshots to help explain the issue. + +## Configuration +```ini +# Paste extension configuration (sanitize sensitive data) +``` + +## Installed Extensions +List other installed extensions that might conflict: +- Extension 1 (version) +- Extension 2 (version) + +## Template Overrides +- [ ] Using template overrides +- [ ] Custom CSS +- [ ] Custom JavaScript + +## Additional Context +- **Multilingual Site**: [Yes / No] +- **Cache Enabled**: [Yes / No] +- **Debug Mode**: [Yes / No] +- **SEF URLs**: [Yes / No] + +## Checklist +- [ ] I have cleared Joomla cache +- [ ] I have disabled other extensions to test for conflicts +- [ ] I have checked Joomla error logs +- [ ] I have tested with a default Joomla template +- [ ] I have checked browser console for JavaScript errors +- [ ] I have searched for similar issues +- [ ] I am using a supported Joomla version From 4f79486cc702501f610dc5073070cc71d54ac00b Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:20:34 +0000 Subject: [PATCH 29/59] chore: add ADR issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/adr.md | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/adr.md diff --git a/.mokogitea/ISSUE_TEMPLATE/adr.md b/.mokogitea/ISSUE_TEMPLATE/adr.md new file mode 100644 index 0000000..eb40760 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/adr.md @@ -0,0 +1,110 @@ +--- +name: Architecture Decision Record (ADR) +about: Propose or document an architectural decision +title: '[ADR] ' +labels: 'architecture, decision' +assignees: '' + +--- + + +## ADR Number +ADR-XXXX + +## Status +- [ ] Proposed +- [ ] Accepted +- [ ] Deprecated +- [ ] Superseded by ADR-XXXX + +## Context +Describe the issue or problem that motivates this decision. + +## Decision +State the architecture decision and provide rationale. + +## Consequences +### Positive +- List positive consequences + +### Negative +- List negative consequences or trade-offs + +### Neutral +- List neutral aspects + +## Alternatives Considered +### Alternative 1 +- Description +- Pros +- Cons +- Why not chosen + +### Alternative 2 +- Description +- Pros +- Cons +- Why not chosen + +## Implementation Plan +1. Step 1 +2. Step 2 +3. Step 3 + +## Stakeholders +- **Decision Makers**: @user1, @user2 +- **Consulted**: @user3, @user4 +- **Informed**: team-name + +## Technical Details +### Architecture Diagram +``` +[Add diagram or link] +``` + +### Dependencies +- Dependency 1 +- Dependency 2 + +### Impact Analysis +- **Performance**: [Impact description] +- **Security**: [Impact description] +- **Scalability**: [Impact description] +- **Maintainability**: [Impact description] + +## Testing Strategy +- [ ] Unit tests +- [ ] Integration tests +- [ ] Performance tests +- [ ] Security tests + +## Documentation +- [ ] Architecture documentation updated +- [ ] API documentation updated +- [ ] Developer guide updated +- [ ] Runbook created + +## Migration Path +Describe how to migrate from current state to new architecture. + +## Rollback Plan +Describe how to rollback if issues occur. + +## Timeline +- **Proposal Date**: +- **Decision Date**: +- **Implementation Start**: +- **Expected Completion**: + +## References +- Related ADRs: +- External resources: +- RFCs: + +## Review Checklist +- [ ] Aligns with enterprise architecture principles +- [ ] Security implications reviewed +- [ ] Performance implications reviewed +- [ ] Cost implications reviewed +- [ ] Compliance requirements met +- [ ] Team consensus achieved From ba5bef267a0d85ba5871a0ea1aeb29093f4a5ef9 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:21:03 +0000 Subject: [PATCH 30/59] chore(version): pre-release bump to 01.07.13-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index e4229b2..53a2029 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.12 +# VERSION: 01.07.13 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index a2f899b..9087b11 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.12 + 01.07.13 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 0cfbe73..9139ade 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.12 + 01.07.13 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 1eed18ac0b01df639793a2c1b280222e9d9637aa Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:21:13 +0000 Subject: [PATCH 31/59] chore: add documentation issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/documentation.md | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/documentation.md diff --git a/.mokogitea/ISSUE_TEMPLATE/documentation.md b/.mokogitea/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000..ed4dabc --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,52 @@ +--- +name: Documentation Issue +about: Report an issue with documentation +title: '[DOCS] ' +labels: 'documentation' +assignees: '' + +--- + + +## Documentation Issue + +**Location**: + + +## Issue Type + +- [ ] Typo or grammar error +- [ ] Outdated information +- [ ] Missing documentation +- [ ] Unclear explanation +- [ ] Broken links +- [ ] Missing examples +- [ ] Other (specify below) + +## Description + + +## Current Content + +``` +Current text here +``` + +## Suggested Improvement + +``` +Suggested text here +``` + +## Additional Context + + +## Standards Alignment +- [ ] Follows MokoStandards documentation guidelines +- [ ] Uses en_US/en_GB localization +- [ ] Includes proper SPDX headers where applicable + +## Checklist +- [ ] I have searched for similar documentation issues +- [ ] I have provided a clear description +- [ ] I have suggested an improvement (if applicable) From 435fe28f0f0dc8fa602e48a40db87fc09a67d365 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:21:59 +0000 Subject: [PATCH 32/59] chore: add question issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/question.md | 82 +++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/question.md diff --git a/.mokogitea/ISSUE_TEMPLATE/question.md b/.mokogitea/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..3175013 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/question.md @@ -0,0 +1,82 @@ +--- +name: Question +about: Ask a question about usage, features, or best practices +title: '[QUESTION] ' +labels: ['question'] +assignees: ['jmiller'] +--- + + +## Question + +**Your question:** + + +## Context + +**What are you trying to accomplish?** + + +**What have you already tried?** + + +**Category**: +- [ ] Script usage +- [ ] Configuration +- [ ] Workflow setup +- [ ] Documentation interpretation +- [ ] Best practices +- [ ] Integration +- [ ] Other: __________ + +## Environment (if relevant) + +**Your setup**: +- Operating System: +- Version: + +## What You've Researched + +**Documentation reviewed**: +- [ ] README.md +- [ ] Project documentation +- [ ] Other (specify): __________ + +**Similar issues/questions found**: +- # +- # + +## Expected Outcome + +**What result are you hoping for?** + + +## Code/Configuration Samples + +**Relevant code or configuration** (if applicable): + +```bash +# Your code here +``` + +## Additional Context + +**Any other relevant information:** + + +**Screenshots** (if helpful): + + +## Urgency + +- [ ] Urgent (blocking work) +- [ ] Normal (can work on other things meanwhile) +- [ ] Low priority (just curious) + +## Checklist + +- [ ] I have searched existing issues and discussions +- [ ] I have reviewed relevant documentation +- [ ] I have provided sufficient context +- [ ] I have included code/configuration samples if relevant +- [ ] This is a genuine question (not a bug report or feature request) From 3152ade88f169e91f6d2c9bc96e052ad90ca79e0 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:22:52 +0000 Subject: [PATCH 33/59] chore: add RFC issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/rfc.md | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/rfc.md diff --git a/.mokogitea/ISSUE_TEMPLATE/rfc.md b/.mokogitea/ISSUE_TEMPLATE/rfc.md new file mode 100644 index 0000000..6f09af7 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/rfc.md @@ -0,0 +1,126 @@ +--- +name: Request for Comments (RFC) +about: Propose a significant change for community discussion +title: '[RFC] ' +labels: 'rfc, discussion' +assignees: '' + +--- + + +## RFC Summary +One-paragraph summary of the proposal. + +## Motivation +Why are we doing this? What use cases does it support? What is the expected outcome? + +## Detailed Design +### Overview +Provide a detailed explanation of the proposed change. + +### API Changes (if applicable) +```php +// Before +function oldApi($param1) { } + +// After +function newApi($param1, $param2) { } +``` + +### User Experience Changes +Describe how users will interact with this change. + +### Implementation Approach +High-level implementation strategy. + +## Drawbacks +Why should we *not* do this? + +## Alternatives +What other designs have been considered? What is the impact of not doing this? + +### Alternative 1 +- Description +- Trade-offs + +### Alternative 2 +- Description +- Trade-offs + +## Adoption Strategy +How will existing users adopt this? Is this a breaking change? + +### Migration Guide +```bash +# Steps to migrate +``` + +### Deprecation Timeline +- **Announcement**: +- **Deprecation**: +- **Removal**: + +## Unresolved Questions +- Question 1 +- Question 2 + +## Future Possibilities +What future work does this enable? + +## Impact Assessment +### Performance +Expected performance impact. + +### Security +Security considerations and implications. + +### Compatibility +- **Backward Compatible**: [Yes / No] +- **Breaking Changes**: [List] + +### Maintenance +Long-term maintenance considerations. + +## Community Input +### Stakeholders +- [ ] Core team +- [ ] Module developers +- [ ] End users +- [ ] Enterprise customers + +### Feedback Period +**Duration**: [e.g., 2 weeks] +**Deadline**: [date] + +## Implementation Timeline +### Phase 1: Design +- [ ] RFC discussion +- [ ] Design finalization +- [ ] Approval + +### Phase 2: Implementation +- [ ] Core implementation +- [ ] Tests +- [ ] Documentation + +### Phase 3: Release +- [ ] Beta release +- [ ] Feedback collection +- [ ] Stable release + +## Success Metrics +How will we measure success? +- Metric 1 +- Metric 2 + +## References +- Related RFCs: +- External documentation: +- Prior art: + +## Open Questions for Community +1. Question 1? +2. Question 2? + +--- +**Note**: This RFC is open for community discussion. Please provide feedback in the comments below. From f5492fcf3a4d3faebe53c25847fe3c1ecc17f5c6 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:23:54 +0000 Subject: [PATCH 34/59] chore: add security issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/security.md | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/security.md diff --git a/.mokogitea/ISSUE_TEMPLATE/security.md b/.mokogitea/ISSUE_TEMPLATE/security.md new file mode 100644 index 0000000..f57b284 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/security.md @@ -0,0 +1,51 @@ +--- +name: Security Vulnerability Report +about: Report a security vulnerability (use only for non-critical issues) +title: '[SECURITY] ' +labels: 'security' +assignees: '' + +--- + + +## ⚠️ IMPORTANT: Private Disclosure Required + +**For critical security vulnerabilities, DO NOT use this template.** +Follow the process in [SECURITY.md](../SECURITY.md) for responsible disclosure. + +Use this template only for: +- Security improvements +- Non-critical security suggestions +- Security documentation updates + +--- + +## Security Issue + +**Severity**: + + +## Description + + +## Affected Components + + +## Suggested Mitigation + + +## Standards Reference +Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)? +- [ ] SPDX license identifiers +- [ ] Secret management +- [ ] Dependency security +- [ ] Access control +- [ ] Other: [specify] + +## Additional Context + + +## Checklist +- [ ] This is NOT a critical vulnerability requiring private disclosure +- [ ] I have reviewed the SECURITY.md policy +- [ ] I have provided sufficient detail for evaluation From f6c1710f97263f46eefb7ac23ec568b79af105b8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:24:15 +0000 Subject: [PATCH 35/59] chore: add version issue template from Template-Joomla --- .mokogitea/ISSUE_TEMPLATE/version.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .mokogitea/ISSUE_TEMPLATE/version.md diff --git a/.mokogitea/ISSUE_TEMPLATE/version.md b/.mokogitea/ISSUE_TEMPLATE/version.md new file mode 100644 index 0000000..6328421 --- /dev/null +++ b/.mokogitea/ISSUE_TEMPLATE/version.md @@ -0,0 +1,24 @@ +--- +name: Version Bump +about: Request or track a version change +title: '[VERSION] ' +labels: 'version, type: version' +assignees: 'jmiller' +--- + +## Version Change + +**Current version**: +**Requested version**: +**Change type**: + +## Reason + + + +## Checklist + +- [ ] README.md `VERSION:` field updated +- [ ] CHANGELOG.md entry added +- [ ] Module descriptor version updated (Dolibarr: `$this->version`, Joomla: ``) +- [ ] All file headers will be auto-propagated by `sync-version-on-merge` workflow From 89ce3d0bf25bfbb78e963b18a9232782a7182b37 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 07:27:24 +0000 Subject: [PATCH 36/59] chore: add branch-protection.yml from Template-Joomla --- .mokogitea/branch-protection.yml | 251 +++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 .mokogitea/branch-protection.yml diff --git a/.mokogitea/branch-protection.yml b/.mokogitea/branch-protection.yml new file mode 100644 index 0000000..2dff8b9 --- /dev/null +++ b/.mokogitea/branch-protection.yml @@ -0,0 +1,251 @@ +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: moko-platform.Automation +# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform +# PATH: /.gitea/workflows/branch-protection.yml +# BRIEF: Apply standardised branch protection rules to all governed repositories +# +# +========================================================================+ +# | BRANCH PROTECTION SETUP | +# +========================================================================+ +# | | +# | Applies protection rules for: main, dev, rc, beta, alpha | +# | | +# | main — Require PR, block rejected reviews, no force push | +# | dev — Allow push, no force push, no delete | +# | rc — Allow push, no force push, no delete | +# | beta — Allow push, no force push, no delete | +# | alpha — Allow push, no force push, no delete | +# | | +# | jmiller has override authority on all branches. | +# | | +# +========================================================================+ + +name: Branch Protection Setup + +on: + schedule: + - cron: '0 2 * * 1' # Weekly Monday 02:00 UTC + workflow_dispatch: + inputs: + dry_run: + description: 'Preview mode (no changes)' + required: false + type: boolean + default: false + repos: + description: 'Comma-separated repo names (empty = all governed repos)' + required: false + type: string + default: '' + +env: + GITEA_URL: https://git.mokoconsulting.tech + GITEA_ORG: MokoConsulting + +permissions: + contents: read + +jobs: + protect: + name: Apply Branch Protection Rules + runs-on: ubuntu-latest + + steps: + - name: Determine target repos + id: repos + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + run: | + API="${GITEA_URL}/api/v1" + + # Platform/standards/infra repos to exclude + EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform MokoTesting" + EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate" + + if [ -n "${{ inputs.repos }}" ]; then + # User-specified repos + REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ') + else + # Fetch all org repos + PAGE=1 + REPOS="" + while true; do + BATCH=$(curl -sS \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \ + | jq -r '.[].name // empty') + [ -z "$BATCH" ] && break + REPOS="$REPOS $BATCH" + PAGE=$((PAGE + 1)) + done + + # Filter out excluded repos + FILTERED="" + for REPO in $REPOS; do + SKIP=false + for EX in $EXCLUDE; do + if [ "$REPO" = "$EX" ]; then + SKIP=true + break + fi + done + if [ "$SKIP" = "false" ]; then + FILTERED="$FILTERED $REPO" + fi + done + REPOS="$FILTERED" + fi + + echo "repos=$REPOS" >> "$GITHUB_OUTPUT" + COUNT=$(echo "$REPOS" | wc -w) + echo "📋 Target repos (${COUNT}): $REPOS" + + - name: Apply protection rules + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + DRY_RUN: ${{ inputs.dry_run || 'false' }} + run: | + API="${GITEA_URL}/api/v1" + REPOS="${{ steps.repos.outputs.repos }}" + + SUCCESS=0 + FAILED=0 + SKIPPED=0 + + # ── Rule definitions ────────────────────────────────────── + # Only the CI bot (jmiller token) can push directly. + # All human contributors must use PRs. + # Force push disabled on all branches. + + RULE_MAIN='{ + "rule_name": "main", + "enable_push": true, + "enable_push_whitelist": true, + "push_whitelist_usernames": ["jmiller"], + "enable_force_push": false, + "enable_force_push_allowlist": false, + "force_push_allowlist_usernames": [], + "enable_merge_whitelist": false, + "required_approvals": 0, + "dismiss_stale_approvals": true, + "block_on_rejected_reviews": true, + "block_on_outdated_branch": false, + "priority": 1 + }' + + RULE_DEV='{ + "rule_name": "dev", + "enable_push": true, + "enable_push_whitelist": true, + "push_whitelist_usernames": ["jmiller"], + "enable_force_push": false, + "enable_force_push_allowlist": false, + "force_push_allowlist_usernames": [], + "enable_merge_whitelist": false, + "required_approvals": 0, + "block_on_rejected_reviews": false, + "priority": 2 + }' + + RULE_RC='{ + "rule_name": "rc", + "enable_push": true, + "enable_push_whitelist": true, + "push_whitelist_usernames": ["jmiller"], + "enable_force_push": false, + "enable_force_push_allowlist": false, + "force_push_allowlist_usernames": [], + "enable_merge_whitelist": false, + "required_approvals": 0, + "block_on_rejected_reviews": false, + "priority": 3 + }' + + RULE_BETA='{ + "rule_name": "beta", + "enable_push": true, + "enable_push_whitelist": true, + "push_whitelist_usernames": ["jmiller"], + "enable_force_push": false, + "enable_force_push_allowlist": false, + "force_push_allowlist_usernames": [], + "enable_merge_whitelist": false, + "required_approvals": 0, + "block_on_rejected_reviews": false, + "priority": 4 + }' + + RULE_ALPHA='{ + "rule_name": "alpha", + "enable_push": true, + "enable_push_whitelist": true, + "push_whitelist_usernames": ["jmiller"], + "enable_force_push": false, + "enable_force_push_allowlist": false, + "force_push_allowlist_usernames": [], + "enable_merge_whitelist": false, + "required_approvals": 0, + "block_on_rejected_reviews": false, + "priority": 5 + }' + + RULES=("$RULE_MAIN" "$RULE_DEV" "$RULE_RC" "$RULE_BETA" "$RULE_ALPHA") + RULE_NAMES=("main" "dev" "rc" "beta" "alpha") + + # ── Apply rules to each repo ────────────────────────────── + for REPO in $REPOS; do + echo "" + echo "═══ ${REPO} ═══" + + for i in "${!RULES[@]}"; do + RULE="${RULES[$i]}" + NAME="${RULE_NAMES[$i]}" + + if [ "$DRY_RUN" = "true" ]; then + echo " [DRY RUN] Would apply rule: ${NAME}" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + # Delete existing rule if present (idempotent recreate) + ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g') + curl -sS -o /dev/null -w "" \ + -X DELETE \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true + + # Create rule + RESPONSE=$(curl -sS -w "\n%{http_code}" \ + -X POST \ + -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$RULE" \ + "${API}/repos/${GITEA_ORG}/${REPO}/branch_protections") + + HTTP=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | sed '$d') + + if [ "$HTTP" = "201" ]; then + echo " ✅ ${NAME}" + SUCCESS=$((SUCCESS + 1)) + else + echo " ❌ ${NAME} (HTTP ${HTTP}): $(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)" + FAILED=$((FAILED + 1)) + fi + done + done + + # ── Summary ─────────────────────────────────────────────── + echo "" + echo "════════════════════════════════════════" + echo " ✅ Success: ${SUCCESS}" + echo " ❌ Failed: ${FAILED}" + echo " ⏭️ Skipped: ${SKIPPED}" + echo "════════════════════════════════════════" + + if [ "$FAILED" -gt 0 ]; then + echo "::warning::${FAILED} rule(s) failed to apply" + fi From 8bba084ee0e43e9413389a5b2bbf80e23bfad3f1 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:31:45 +0000 Subject: [PATCH 37/59] chore(version): pre-release bump to 01.07.14-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 53a2029..981dec4 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.13 +# VERSION: 01.07.14 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 9087b11..ca8e6c4 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.13 + 01.07.14 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 9139ade..3722746 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.13 + 01.07.14 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 040eeac850d74a93794f181dd0ebaf9ccbd115dd Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:36:32 +0000 Subject: [PATCH 38/59] chore(version): pre-release bump to 01.07.15-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 981dec4..c5c13bf 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.14 +# VERSION: 01.07.15 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index ca8e6c4..578c391 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.14 + 01.07.15 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 3722746..ec00a73 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.14 + 01.07.15 2026-06-11 Moko Consulting hello@mokoconsulting.tech From aba3d30153657f29fe051389f45a73be0ead72b0 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:41:13 +0000 Subject: [PATCH 39/59] chore(version): pre-release bump to 01.07.16-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index c5c13bf..a3a466b 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.15 +# VERSION: 01.07.16 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 578c391..98147e3 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.15 + 01.07.16 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index ec00a73..54dca3a 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.15 + 01.07.16 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 3113d684a0a777016576cf377c931d1b0c9f1f3e Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:47:18 +0000 Subject: [PATCH 40/59] chore(version): pre-release bump to 01.07.17-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index a3a466b..c7d872d 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.16 +# VERSION: 01.07.17 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 98147e3..0687818 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.16 + 01.07.17 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 54dca3a..38f8901 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.16 + 01.07.17 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 4a3277471c79fb41d66a89e94fb00741bee4e245 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 07:55:06 +0000 Subject: [PATCH 41/59] chore(version): pre-release bump to 01.07.18-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index c7d872d..5d2a44d 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.17 +# VERSION: 01.07.18 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 0687818..d97cb86 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.17 + 01.07.18 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 38f8901..8a974fa 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.17 + 01.07.18 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 455707591ac40eaa3e153abfeec730b5f1b5946e Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Sun, 28 Jun 2026 18:59:12 +0000 Subject: [PATCH 42/59] feat: add license key warning on install/update --- source/script.php | 72 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/source/script.php b/source/script.php index d76d3d4..045022c 100644 --- a/source/script.php +++ b/source/script.php @@ -1,8 +1,74 @@ warnMissingLicenseKey(); + } + + private function warnMissingLicenseKey(): void + { + try + { + $db = Factory::getDbo(); + $app = Factory::getApplication(); + + $query = $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('%MokoSuiteNPO%') + . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoSuiteNPO%') . ')') + ->setLimit(1); + $db->setQuery($query); + $site = $db->loadObject(); + + if ($site) + { + $extraQuery = (string) ($site->extra_query ?? ''); + + if (!empty($extraQuery) && strpos($extraQuery, 'dlid=') !== false) + { + parse_str($extraQuery, $parsed); + + if (!empty($parsed['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'; + } + + $app->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) + { + // Silent — avoid breaking install if update_sites query fails + } + } } From fdb25cf999ff0c4bf1b93857300ebf5eba380bac Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 19:00:49 +0000 Subject: [PATCH 43/59] chore(version): auto-bump patch 01.07.19-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 5d2a44d..681fa6e 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.18 +# VERSION: 01.07.19 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index d97cb86..deff2ec 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.18 + 01.07.19 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 8a974fa..19e309b 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.18 + 01.07.19 2026-06-11 Moko Consulting hello@mokoconsulting.tech From e8e7c9aa3666b182767e1c962243b0379ed4c20d Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Sun, 28 Jun 2026 19:01:03 +0000 Subject: [PATCH 44/59] chore(version): pre-release bump to 01.07.20-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 681fa6e..30e7d87 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.19 +# VERSION: 01.07.20 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index deff2ec..40ab256 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.19 + 01.07.20 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 19e309b..b3fd73d 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.19 + 01.07.20 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 22000c099e06a387d898dd59a95c806e4e50e398 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 29 Jun 2026 15:11:45 +0000 Subject: [PATCH 45/59] chore: migrate update server URLs to MokoGitea --- source/pkg_mokosuitenpo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index b3fd73d..31ccc44 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -23,6 +23,6 @@ - https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteNPO/updates.xml + https://git.mokoconsulting.tech/api/packages/MokoConsulting/generic/MokoSuiteNPO/latest/updates.xml From cc4479bf062dd94353af7517d15c4e842f6c51e6 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 29 Jun 2026 15:12:32 +0000 Subject: [PATCH 46/59] chore(version): pre-release bump to 01.07.21-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 30e7d87..b5c6159 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.20 +# VERSION: 01.07.21 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 40ab256..a775561 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.20 + 01.07.21 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 31ccc44..ad6a645 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.20 + 01.07.21 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 705d40d50faf3c5d271c5d929fb5ad9e598a8c88 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 29 Jun 2026 15:23:53 +0000 Subject: [PATCH 47/59] chore(version): auto-bump patch 01.07.22-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index b5c6159..8395760 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.21 +# VERSION: 01.07.22 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index a775561..05b9a22 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.21 + 01.07.22 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index ad6a645..0d656b0 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.21 + 01.07.22 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 61d4f06b288ffbfbb073957b95ec1ce9ccdd1ec9 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 29 Jun 2026 15:24:08 +0000 Subject: [PATCH 48/59] chore(version): pre-release bump to 01.07.23-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 8395760..bb69873 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.22 +# VERSION: 01.07.23 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 05b9a22..0ccf933 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.22 + 01.07.23 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 0d656b0..481ae3c 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.22 + 01.07.23 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 1eee4207fc20346684f6a07087569364a32afc36 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 30 Jun 2026 13:15:41 -0500 Subject: [PATCH 49/59] chore: cleanup workflows, add manual dispatch to pre-release - Remove old build.yaml (hardcoded, references updates.xml) - Remove duplicate build-release.yml - Add pre-release.yml with workflow_dispatch for manual triggering - All releases marked as pre-release until stable testing complete --- .gitea/workflows/build.yaml | 33 ---------------- .gitea/workflows/pre-release.yml | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 33 deletions(-) delete mode 100644 .gitea/workflows/build.yaml create mode 100644 .gitea/workflows/pre-release.yml diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml deleted file mode 100644 index 5281af2..0000000 --- a/.gitea/workflows/build.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: Build Package -on: - push: - tags: - - 'v*' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Build package ZIP - run: | - cd source - # Create individual package ZIPs - for pkg_dir in packages/*/; do - pkg_name=$(basename "$pkg_dir") - cd "$pkg_dir" - zip -r "../../${pkg_name}.zip" . -x "*.git*" - cd ../.. - done - # Create main package ZIP with all sub-packages + manifest - zip -j "pkg_mokosuitenpo.zip" pkg_*.xml script.php updates.xml *.zip 2>/dev/null || true - ls -la *.zip - - - name: Create Release - uses: softprops/action-gh-release@v1 - with: - files: source/pkg_mokosuitenpo.zip - generate_release_notes: true diff --git a/.gitea/workflows/pre-release.yml b/.gitea/workflows/pre-release.yml new file mode 100644 index 0000000..7e4d40e --- /dev/null +++ b/.gitea/workflows/pre-release.yml @@ -0,0 +1,66 @@ +name: Pre-Release Package + +on: + push: + tags: + - "v*" + workflow_dispatch: + inputs: + version: + description: "Version (e.g. 1.0.0-alpha.1)" + required: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Determine version + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + else + VERSION="${GITHUB_REF#refs/tags/v}" + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + fi + + - name: Build package zip + run: | + cd source + for dir in packages/*/; do + pkg_name=$(basename "$dir") + cd "$dir" + zip -r "../../${pkg_name}.zip" . -x "*.git*" + cd ../.. + done + mkdir -p pkg_build + mv *.zip pkg_build/ + cp pkg_*.xml pkg_build/ 2>/dev/null || true + cp script.php pkg_build/ 2>/dev/null || true + cd pkg_build + zip -r "../${{ github.event.repository.name }}-${{ steps.version.outputs.VERSION }}.zip" . + + - name: Create Pre-Release + uses: actions/create-release@v1 + id: create_release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.version.outputs.TAG }} + release_name: "${{ github.event.repository.name }} ${{ steps.version.outputs.TAG }}" + draft: false + prerelease: true + + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./source/${{ github.event.repository.name }}-${{ steps.version.outputs.VERSION }}.zip + asset_name: ${{ github.event.repository.name }}-${{ steps.version.outputs.VERSION }}.zip + asset_content_type: application/zip From 69af5839b99870de431509e3f763034036abb9d8 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 30 Jun 2026 18:15:52 +0000 Subject: [PATCH 50/59] chore(version): pre-release bump to 01.07.24-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index bb69873..43d7107 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.23 +# VERSION: 01.07.24 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 0ccf933..7e8318e 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.23 + 01.07.24 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 481ae3c..83ff126 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.23 + 01.07.24 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 3f5dccc1dcd4064b104af690a10baee8b9e143d2 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 30 Jun 2026 18:30:52 +0000 Subject: [PATCH 51/59] chore(version): pre-release bump to 01.07.28-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 43d7107..91ca2ac 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.24 +# VERSION: 01.07.28 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 7e8318e..ac0e63e 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.24 + 01.07.28 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 83ff126..3e6f378 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.24 + 01.07.28 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 445394d4ae013b21cd474e3794c55c4c850655a5 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Mon, 6 Jul 2026 11:20:32 -0500 Subject: [PATCH 52/59] fix: honest installer success message Gate the installer's license / next-steps success message behind a verification that every child extension declared in the package manifest actually landed in #__extensions. If any bundled extension is missing, show an honest error instead of the success/license message and return. Fails open: any error (unreadable manifest, query failure) is treated as "nothing missing" so a transient glitch never fakes a failure. Housekeeping (dlid restore, plugin enable) still runs unconditionally. Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R --- CHANGELOG.md | 4 ++ source/script.php | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2eefe8..86e2e5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # MokoSuite NPO Nonprofit management for MokoSuite. Layer 2 add-on (requires CRM). +## [Unreleased] +### Fixed +- Installer no longer shows the "license / next-steps" success message when a bundled child extension failed to install. The package `postflight` now verifies every child declared in the manifest actually landed in `#__extensions` and shows an honest error instead. Fails open so a transient glitch never fakes a failure. + ## Features - Donor management with giving levels - Donation tracking with fund allocation diff --git a/source/script.php b/source/script.php index 045022c..7b403b6 100644 --- a/source/script.php +++ b/source/script.php @@ -19,9 +19,112 @@ class Pkg_MokoSuiteNPOInstallerScript { public function postflight(string $type, InstallerAdapter $adapter): void { + // Be honest about success. Joomla's package installer only LOGS a failed + // child sub-install but still runs this postflight, so don't show the + // license / next-steps message if a bundled extension is actually missing. + // Fails open (see missingChildExtensions) so a glitch never fakes a failure. + $missing = $this->missingChildExtensions($adapter); + + if (!empty($missing)) + { + Factory::getApplication()->enqueueMessage( + '

MokoSuiteNPO did not install correctly.

' + . '

The following bundled extensions are missing: ' + . htmlspecialchars(implode(', ', $missing), ENT_QUOTES) . '

' + . '

Please uninstall MokoSuiteNPO and reinstall the full package.

', + 'error' + ); + + return; + } + $this->warnMissingLicenseKey(); } + /** + * Verify every child extension declared in the package manifest actually + * landed in #__extensions. Returns readable labels of any that are missing. + * + * Matching per Joomla's #__extensions uniqueness: + * - type = the "type" attribute + * - element = the "id" attribute, EXCEPT for plugins where the + * manifest declares the full plg__ id, so a + * leading plg__ is stripped to get the real element + * - plugins ALSO match folder = the "group" attribute + * + * FAILS OPEN: any error (unreadable manifest, query failure) returns [] so a + * transient glitch never turns a good install into a false failure. + * + * @param InstallerAdapter $adapter The package installer adapter. + * + * @return string[] Labels of missing child extensions. + */ + private function missingChildExtensions(InstallerAdapter $adapter): array + { + try + { + $manifest = $adapter->getParent()->getManifest(); + + if (!$manifest || !isset($manifest->files) || !isset($manifest->files->file)) + { + return []; + } + + $db = Factory::getDbo(); + $missing = []; + + foreach ($manifest->files->file as $file) + { + $attrs = $file->attributes(); + $id = isset($attrs['id']) ? (string) $attrs['id'] : ''; + $exType = isset($attrs['type']) ? (string) $attrs['type'] : ''; + + if ($id === '' || $exType === '') + { + continue; + } + + $group = isset($attrs['group']) ? (string) $attrs['group'] : ''; + $element = $id; + + // Plugin element in #__extensions is the id minus any leading plg__. + if ($exType === 'plugin' && $group !== '') + { + $prefix = 'plg_' . $group . '_'; + + if (strpos($element, $prefix) === 0) + { + $element = substr($element, \strlen($prefix)); + } + } + + $query = $db->getQuery(true) + ->select('COUNT(*)') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote($element)) + ->where($db->quoteName('type') . ' = ' . $db->quote($exType)); + + if ($exType === 'plugin' && $group !== '') + { + $query->where($db->quoteName('folder') . ' = ' . $db->quote($group)); + } + + if ((int) $db->setQuery($query)->loadResult() === 0) + { + $label = trim((string) $file); + $missing[] = $label !== '' ? preg_replace('/\.zip$/i', '', $label) : $id; + } + } + + return $missing; + } + catch (\Throwable $e) + { + // Fail open — never fake a failure on a glitch. + return []; + } + } + private function warnMissingLicenseKey(): void { try From 38eddc2852ac6409e65d104fecc8c474d1f8adf6 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 6 Jul 2026 16:21:41 +0000 Subject: [PATCH 53/59] chore(version): pre-release bump to 01.07.30-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 91ca2ac..44e04f5 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.28 +# VERSION: 01.07.30 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index ac0e63e..410b490 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.28 + 01.07.30 8.3 MokoSuite NPO component Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 3e6f378..aaa73af 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.28 + 01.07.30 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 9e314a86ccaa7e8f2f9a6ebf76ee1915772d7bd9 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 6 Jul 2026 22:45:41 +0000 Subject: [PATCH 54/59] feat(menu): add COM_MOKOSUITENPO_SHORT short-name constant (#37) Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R --- .../admin/language/en-GB/com_mokosuitenpo.sys.ini | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 source/packages/com_mokosuitenpo/admin/language/en-GB/com_mokosuitenpo.sys.ini diff --git a/source/packages/com_mokosuitenpo/admin/language/en-GB/com_mokosuitenpo.sys.ini b/source/packages/com_mokosuitenpo/admin/language/en-GB/com_mokosuitenpo.sys.ini new file mode 100644 index 0000000..549fcdc --- /dev/null +++ b/source/packages/com_mokosuitenpo/admin/language/en-GB/com_mokosuitenpo.sys.ini @@ -0,0 +1,3 @@ +COM_MOKOSUITENPO="MokoSuite NPO" +COM_MOKOSUITENPO_SHORT="NPO" +COM_MOKOSUITENPO_XML_DESCRIPTION="MokoSuite NPO component." From 9d7482c3e82194d46d907defaafa5f763514e044 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Mon, 6 Jul 2026 22:46:00 +0000 Subject: [PATCH 55/59] feat(menu): use COM_MOKOSUITENPO_SHORT + wire admin language (#37) Claude-Session: https://claude.ai/code/session_01B9aZHSWbiiZykJD88pYx8R --- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 410b490..a447053 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -9,11 +9,14 @@ https://mokoconsulting.tech 01.07.30 8.3 - MokoSuite NPO component + COM_MOKOSUITENPO_XML_DESCRIPTION Moko\Component\MokoSuiteNpo - MokoSuite NPO - srcservicestmpl + COM_MOKOSUITENPO_SHORT + languagesrcservicestmpl + + en-GB/com_mokosuitenpo.sys.ini + srctmpl src From d3f60b2c00e6b4b284bd9e27686a1bc7f1614ddf Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 6 Jul 2026 22:46:44 +0000 Subject: [PATCH 56/59] chore(version): pre-release bump to 01.07.31-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 44e04f5..3dc976e 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.30 +# VERSION: 01.07.31 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index a447053..a56c9dc 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.30 + 01.07.31 8.3 COM_MOKOSUITENPO_XML_DESCRIPTION Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index aaa73af..6856a4e 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.30 + 01.07.31 2026-06-11 Moko Consulting hello@mokoconsulting.tech From fbd2d92b931f0a98c7d822ae7d8c94fa57e6d0c0 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 6 Jul 2026 22:47:19 +0000 Subject: [PATCH 57/59] chore(version): pre-release bump to 01.07.32-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 3dc976e..242bc6f 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.31 +# VERSION: 01.07.32 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index a56c9dc..74e7ef6 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.31 + 01.07.32 8.3 COM_MOKOSUITENPO_XML_DESCRIPTION Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 6856a4e..26f1763 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.31 + 01.07.32 2026-06-11 Moko Consulting hello@mokoconsulting.tech From fe25cae9f9aa3bd1d5953ffea1d404850dfd57f6 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Mon, 6 Jul 2026 22:47:34 +0000 Subject: [PATCH 58/59] chore(version): pre-release bump to 01.07.33-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 242bc6f..6345c7c 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.32 +# VERSION: 01.07.33 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 74e7ef6..15962c6 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.32 + 01.07.33 8.3 COM_MOKOSUITENPO_XML_DESCRIPTION Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index 26f1763..a50d9d9 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.32 + 01.07.33 2026-06-11 Moko Consulting hello@mokoconsulting.tech From 75767c8c1a779b1a17bae9d8cc2f62a37ea2d163 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Tue, 7 Jul 2026 10:17:34 +0000 Subject: [PATCH 59/59] chore(version): pre-release bump to 01.07.34-dev [skip ci] --- .mokogitea/workflows/issue-branch.yml | 2 +- source/packages/com_mokosuitenpo/mokosuitenpo.xml | 2 +- source/pkg_mokosuitenpo.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 6345c7c..ede1236 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.07.33 +# VERSION: 01.07.34 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitenpo/mokosuitenpo.xml b/source/packages/com_mokosuitenpo/mokosuitenpo.xml index 15962c6..631333f 100644 --- a/source/packages/com_mokosuitenpo/mokosuitenpo.xml +++ b/source/packages/com_mokosuitenpo/mokosuitenpo.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 01.07.33 + 01.07.34 8.3 COM_MOKOSUITENPO_XML_DESCRIPTION Moko\Component\MokoSuiteNpo diff --git a/source/pkg_mokosuitenpo.xml b/source/pkg_mokosuitenpo.xml index a50d9d9..abc7582 100644 --- a/source/pkg_mokosuitenpo.xml +++ b/source/pkg_mokosuitenpo.xml @@ -2,7 +2,7 @@ Package - MokoSuite NPO mokosuitenpo - 01.07.33 + 01.07.34 2026-06-11 Moko Consulting hello@mokoconsulting.tech