Compare commits

..

26 Commits

Author SHA1 Message Date
gitea-actions[bot] 16c2fd35ff chore(version): auto-bump patch 01.08.11-dev [skip ci] 2026-06-27 19:51:53 +00:00
jmiller 1b25f852a8 feat(#156): add social preview panel for article editor
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
PreviewHelper renders platform-specific mockups (Twitter, Facebook,
LinkedIn, Mastodon, Bluesky, Telegram) showing how cross-posted content
will appear. PreviewController serves AJAX requests from the article
editor. Content plugin injects platform selector and preview button
into the Cross-Posting fieldset for existing articles.

Authored-by: Moko Consulting
2026-06-27 14:51:03 -05:00
gitea-actions[bot] ce9d72b50d chore(version): pre-release bump to 01.08.10-dev [skip ci] 2026-06-27 00:11:16 +00:00
gitea-actions[bot] 92358a673b chore(version): pre-release bump to 01.08.09-dev [skip ci] 2026-06-25 19:46:34 +00:00
gitea-actions[bot] 99308cd7a4 chore(version): pre-release bump to 01.08.08-dev [skip ci] 2026-06-25 17:09:50 +00:00
jmiller 561ba24090 Merge pull request 'fix: use typed Joomla 6 event parameters, remove legacy fallbacks' (#184) from fix/joomla6-event-handlers into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
2026-06-25 17:09:13 +00:00
jmiller 3e1cb9a500 fix: use typed Joomla 6 event parameters, remove legacy fallbacks
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 4s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 27s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Remove func_get_arg() legacy fallbacks from onContentBeforeDisplay,
onContentAfterSave, and onContentChangeState. All methods now use
typed event parameters (Joomla 6 only).
2026-06-25 12:08:54 -05:00
gitea-actions[bot] 5ae8e3e001 chore(version): pre-release bump to 01.08.07-dev [skip ci] 2026-06-25 16:27:32 +00:00
jmiller faea3637e0 Merge pull request 'fix: add SQL update file to match manifest version' (#183) from fix/schema-version-file into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
fix: add SQL update file to match manifest version
2026-06-25 16:26:37 +00:00
jmiller 79eaa5217d fix: add SQL update file to match manifest version
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Failing after 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 16s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Joomla's Database view requires a SQL update file matching the manifest
version. Missing file causes persistent schema version mismatch warning.
2026-06-25 11:25:24 -05:00
gitea-actions[bot] 0e0891f1a8 chore(version): pre-release bump to 01.08.05-dev [skip ci] 2026-06-25 16:15:51 +00:00
gitea-actions[bot] 33aaf666ae chore(version): pre-release bump to 01.08.04-dev [skip ci] 2026-06-25 16:15:19 +00:00
gitea-actions[bot] a634938799 chore(version): auto-bump patch 01.08.03-dev [skip ci] 2026-06-25 16:15:03 +00:00
jmiller 14ff4ab2f1 chore: update changelog with Joomla 6 webservices fix
Universal: Auto Version Bump / Version Bump (push) Successful in 17s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 16s
2026-06-25 11:13:41 -05:00
gitea-actions[bot] b3de21e7d1 chore(version): pre-release bump to 01.08.02-dev [skip ci] 2026-06-25 14:54:01 +00:00
gitea-actions[bot] 72a373b17c chore(version): auto-bump patch 01.07.04-dev [skip ci] 2026-06-25 14:53:44 +00:00
jmiller bc290f3bed fix: Joomla 6 compat for webservices API route event
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 22s
Joomla 6 passes a BeforeApiRouteEvent object instead of the router
directly. Extract the router from the event for Joomla 5/6 dual compat.
2026-06-25 09:53:29 -05:00
gitea-actions[bot] a4704ad267 chore(version): pre-release bump to 01.07.03-dev [skip ci] 2026-06-23 22:53:09 +00:00
gitea-actions[bot] d1762ad5df chore(version): auto-bump patch 01.07.02-dev [skip ci] 2026-06-23 22:52:52 +00:00
Jonathan Miller df1467c518 Merge branch 'dev' of https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteCross into dev
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 16s
Universal: Auto Version Bump / Version Bump (push) Successful in 17s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 17s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 38s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-23 17:52:30 -05:00
Jonathan Miller 7cdd97ca59 chore: re-remove deploy-manual.yml synced from template 2026-06-23 17:51:24 -05:00
Jonathan Miller 5b36d10b04 Merge remote-tracking branch 'origin/main' into dev 2026-06-23 17:34:43 -05:00
gitea-actions[bot] 56699fdd4d chore(version): pre-release bump to 01.07.01-dev [skip ci] 2026-06-23 22:27:51 +00:00
gitea-actions[bot] fcf1cc41c8 chore(version): auto-bump patch 01.06.10-dev [skip ci] 2026-06-23 22:27:41 +00:00
Jonathan Miller b8640ccb1d fix: content plugin func_get_arg crash on non-article saves
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
onContentAfterSave and onContentChangeState fire for ALL content types
in Joomla (articles, update sites, installer, etc). The legacy fallback
used func_get_arg() without checking argument count, crashing when
com_installer saved update sites (only 1 arg, not 3).

Fix: check context early in the event object path, and guard legacy
path with func_num_args() >= N before calling func_get_arg().
2026-06-23 17:25:59 -05:00
gitea-actions[bot] ca06298e64 chore(version): pre-release bump to 01.06.09-dev [skip ci] 2026-06-23 21:51:30 +00:00
72 changed files with 1787 additions and 1645 deletions
+66 -66
View File
@@ -1,66 +1,66 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup mokocli tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/mokocli/cli" ]; then
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+11 -12
View File
@@ -27,7 +27,7 @@ name: "Universal: Build & Release"
on:
pull_request:
types: [opened, synchronize, closed]
types: [opened, closed]
branches:
- main
paths-ignore:
@@ -52,7 +52,7 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
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 }}
@@ -66,7 +66,6 @@ jobs:
runs-on: release
if: >-
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event.action == 'synchronize' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
steps:
@@ -102,7 +101,7 @@ jobs:
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
- name: Checkout rc and configure git
@@ -121,7 +120,7 @@ jobs:
- name: Update RC release notes from CHANGELOG.md
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Extract [Unreleased] section from changelog
@@ -269,7 +268,7 @@ jobs:
!startsWith(steps.platform.outputs.platform, 'joomla')
run: |
VERSION="${{ steps.version.outputs.version }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
SEMVER_TAG="v${VERSION}"
@@ -294,7 +293,7 @@ jobs:
- name: Update release notes and promote changelog
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Get the stable release info (version and ID)
@@ -363,7 +362,7 @@ jobs:
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
@@ -392,7 +391,7 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc)
@@ -416,7 +415,7 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}"
@@ -437,7 +436,7 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true
@@ -463,5 +462,5 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi
-6
View File
@@ -13,12 +13,6 @@
name: "Generic: Project CI"
on:
pull_request:
branches:
- main
- dev
- dev/**
- rc/**
workflow_dispatch:
permissions:
@@ -1,68 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
# VERSION: 01.00.00
# BRIEF: Reusable workflow — creates/updates a Gitea issue when a CI gate fails.
# Clones MokoCLI and runs cli/ci_issue_reporter.sh.
name: "Universal: CI Issue Reporter"
on:
workflow_call:
inputs:
gate:
description: "CI gate name (e.g. PR Validation, Repository Health)"
required: true
type: string
details:
description: "Human-readable failure description"
required: true
type: string
severity:
description: "error or warning"
required: false
type: string
default: "error"
workflow:
description: "Workflow name for the issue title"
required: false
type: string
default: ""
secrets:
MOKOGITEA_TOKEN:
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
report:
name: "Report: ${{ inputs.gate }}"
runs-on: ubuntu-latest
steps:
- name: Clone MokoCLI
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
- name: Report CI failure
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x /tmp/mokocli/cli/ci_issue_reporter.sh
/tmp/mokocli/cli/ci_issue_reporter.sh \
--gate "${{ inputs.gate }}" \
--details "${{ inputs.details }}" \
--severity "${{ inputs.severity }}" \
--workflow "${{ inputs.workflow }}"
+10 -10
View File
@@ -21,7 +21,7 @@ permissions:
contents: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
cleanup:
@@ -33,17 +33,17 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
token: ${{ secrets.GA_TOKEN }}
- name: Delete merged branches
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0
@@ -56,7 +56,7 @@ jobs:
# Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
# Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0
for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
-126
View File
@@ -1,126 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# 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:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_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
+5 -5
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 01.00.00
# VERSION: 01.08.11
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
@@ -28,8 +28,8 @@ jobs:
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
@@ -58,7 +58,7 @@ jobs:
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
REPO_URL="${GITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \
File diff suppressed because it is too large Load Diff
+1 -6
View File
@@ -7,7 +7,7 @@
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.02.00
# VERSION: 05.01.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release"
@@ -59,11 +59,6 @@ jobs:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }}
submodules: recursive
- name: Update submodules to main
run: |
git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
- name: Setup mokocli tools
env:
+13 -18
View File
@@ -29,20 +29,12 @@ jobs:
steps:
- name: Rename branch
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
REPO: ${{ github.repository }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
set -euo pipefail
# BRANCH is attacker-controlled (PR head ref). Strict allowlist before ANY use.
if ! printf '%s' "$BRANCH" | grep -Eq '^rc/[A-Za-z0-9._/-]+$'; then
echo "::error::Refusing unsafe branch name: $BRANCH"; exit 1
fi
BRANCH="${{ github.event.pull_request.head.ref }}"
SUFFIX="${BRANCH#rc/}"
DEV_BRANCH="dev/${SUFFIX}"
API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Create dev/ branch from rc/ branch
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
@@ -50,22 +42,25 @@ jobs:
-H "Content-Type: application/json" \
-d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \
"${API}" 2>/dev/null || true)
if [ "$STATUS" = "201" ]; then
echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"
exit 1
fi
# Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));')
# Delete rc/ branch
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${TOKEN}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
fi
echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY"
echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -48,7 +48,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
token: ${{ secrets.MOKOGITEA_TOKEN || secrets.GA_TOKEN || github.token }}
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
+4 -12
View File
@@ -13,7 +13,6 @@
name: "Universal: Workflow Sync Trigger"
on:
workflow_dispatch:
pull_request:
types: [closed]
branches:
@@ -27,9 +26,8 @@ jobs:
name: Sync workflows to live repos
runs-on: ubuntu-latest
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]'))
github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')
steps:
- name: Determine platform from repo name
@@ -51,14 +49,8 @@ jobs:
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
- name: Install PHP
run: |
if ! command -v php &> /dev/null; then
apt-get update -qq && apt-get install -y -qq php-cli php-json php-curl > /dev/null 2>&1
fi
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
- name: Install dependencies
run: |
+24 -3
View File
@@ -1,9 +1,8 @@
# Changelog
## [Unreleased]
## [01.08.00] --- 2026-06-23
## [01.08.00] --- 2026-06-23
### Fixed
- Webservices plugin Joomla 6 compatibility — `onBeforeApiRoute` receives `BeforeApiRouteEvent` object, extract router via `$event->getRouter()`
## [01.07.00] --- 2026-06-23
@@ -16,6 +15,7 @@
### Fixed
- **License warning**: Removed duplicate from system plugin (install script already shows it)
- **Content plugin**: Fixed func_get_arg crash when non-article content is saved (e.g. update sites, installer)
## [01.05.00] --- 2026-06-23
@@ -52,3 +52,24 @@
- **Bluesky**: Replaced md5() with hash('sha256', ...) for cache key
- **ServiceController**: Exception details no longer exposed to client
- **License warning**: Removed duplicate from system plugin -- install script already shows it with direct edit link
## [01.04.01] --- 2026-06-21
## [01.04.01] --- 2026-06-21
## [01.04.00] --- 2026-06-21
### Fixed
- **Package manifest**: Added missing `plg_system_mokosuitecross_events` and `plg_system_mokosuitecross_gallery` to `pkg_mokosuitecross.xml` — these system plugins were not installed with the package
- **Cleanup**: Removed old `src/` directory (pre-rename cruft with `mokojoomcross` files)
## [01.03.00] --- 2026-06-21
<!-- VERSION: 01.08.11 -->
All notable changes to MokoSuiteCross will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
+1 -1
View File
@@ -1,6 +1,6 @@
# MokoSuiteCross
<!-- VERSION: 01.08.00 -->
<!-- VERSION: 01.08.11 -->
Cross-posting Joomla content to social media, email marketing, and chat platforms for Joomla 5/6.
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="component" method="upgrade">
<name>com_mokosuitecross</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -0,0 +1 @@
/* 01.08.05 — no schema changes */
@@ -0,0 +1 @@
/* 01.08.07 — no schema changes */
@@ -0,0 +1 @@
/* 01.08.08 — no schema changes */
@@ -0,0 +1 @@
/* 01.08.09 — no schema changes */
@@ -0,0 +1 @@
/* 01.08.10 — no schema changes */
@@ -0,0 +1 @@
/* 01.08.11 — no schema changes */
@@ -0,0 +1,86 @@
<?php
/**
* @package MokoSuiteCross
* @subpackage com_mokosuitecross
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
* SPDX-License-Identifier: GPL-3.0-or-later
*/
namespace Joomla\Component\MokoSuiteCross\Administrator\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\MokoSuiteCross\Administrator\Helper\CrossPostDispatcher;
use Joomla\Component\MokoSuiteCross\Administrator\Helper\PreviewHelper;
class PreviewController extends BaseController
{
public function render(): void
{
if (!Session::checkToken('get')) {
echo json_encode(['error' => 'Invalid token']);
$this->app->close();
return;
}
$articleId = $this->input->getInt('article_id', 0);
$platform = $this->input->getCmd('platform', 'twitter');
if ($articleId < 1) {
echo json_encode(['error' => 'Missing article ID']);
$this->app->close();
return;
}
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__content'))
->where($db->quoteName('id') . ' = ' . $articleId);
$db->setQuery($query);
$article = $db->loadObject();
if (!$article) {
echo json_encode(['error' => 'Article not found']);
$this->app->close();
return;
}
$meta = CrossPostDispatcher::buildArticleMeta($article);
$title = $meta['{title}'] ?? '';
$text = $meta['{introtext}'] ?? '';
$url = $meta['{url}'] ?? '';
$imageUrl = $meta['{image}'] ?? '';
$authorName = $meta['{author}'] ?? '';
$supportedPlatforms = PreviewHelper::getSupportedPlatforms();
$html = '';
if ($platform === 'all') {
foreach ($supportedPlatforms as $p) {
$html .= '<div style="margin-bottom:20px;">'
. '<div style="font-weight:600;font-size:13px;color:#666;margin-bottom:6px;text-transform:uppercase;">' . htmlspecialchars(ucfirst($p)) . '</div>'
. PreviewHelper::render($p, $title, $text, $url, $imageUrl, $authorName)
. '</div>';
}
} else {
$html = PreviewHelper::render($platform, $title, $text, $url, $imageUrl, $authorName);
}
$this->app->setHeader('Content-Type', 'text/html; charset=utf-8');
echo $html;
$this->app->close();
}
}
@@ -0,0 +1,207 @@
<?php
/**
* @package MokoSuiteCross
* @subpackage com_mokosuitecross
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
* SPDX-License-Identifier: GPL-3.0-or-later
*/
namespace Joomla\Component\MokoSuiteCross\Administrator\Helper;
defined('_JEXEC') or die;
class PreviewHelper
{
public static function render(string $platform, string $title, string $text, string $url, string $imageUrl = '', string $authorName = ''): string
{
$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
$url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
$authorName = htmlspecialchars($authorName, ENT_QUOTES, 'UTF-8');
$imageHtml = '';
if (!empty($imageUrl)) {
$imageUrl = htmlspecialchars($imageUrl, ENT_QUOTES, 'UTF-8');
$imageHtml = '<img src="' . $imageUrl . '" alt="" style="width:100%;max-height:260px;object-fit:cover;border-radius:8px;margin:8px 0;">';
}
return match ($platform) {
'twitter' => self::renderTwitter($title, $text, $url, $imageHtml, $authorName),
'facebook' => self::renderFacebook($title, $text, $url, $imageHtml, $authorName),
'mastodon' => self::renderMastodon($title, $text, $url, $imageHtml, $authorName),
'linkedin' => self::renderLinkedIn($title, $text, $url, $imageHtml, $authorName),
'bluesky' => self::renderBluesky($title, $text, $url, $imageHtml, $authorName),
'telegram' => self::renderTelegram($title, $text, $url, $imageHtml),
default => self::renderGeneric($platform, $title, $text, $url, $imageHtml),
};
}
public static function getSupportedPlatforms(): array
{
return ['twitter', 'facebook', 'mastodon', 'linkedin', 'bluesky', 'telegram'];
}
private static function renderTwitter(string $title, string $text, string $url, string $imageHtml, string $author): string
{
$displayText = !empty($text) ? $text : $title;
$charCount = mb_strlen(strip_tags($displayText));
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #cfd9de;border-radius:16px;padding:12px 16px;background:#fff;">
<div style="display:flex;align-items:center;margin-bottom:8px;">
<div style="width:40px;height:40px;border-radius:50%;background:#1da1f2;margin-right:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:bold;font-size:16px;">X</div>
<div>
<div style="font-weight:700;font-size:15px;color:#0f1419;">{$author}</div>
<div style="color:#536471;font-size:13px;">@username</div>
</div>
</div>
<div style="font-size:15px;line-height:1.4;color:#0f1419;margin-bottom:8px;">{$displayText}</div>
{$imageHtml}
<div style="margin-top:8px;padding:10px 12px;border:1px solid #cfd9de;border-radius:12px;background:#f7f9f9;">
<div style="font-size:13px;color:#536471;margin-bottom:2px;">yoursite.com</div>
<div style="font-size:15px;font-weight:600;color:#0f1419;">{$title}</div>
</div>
<div style="color:#536471;font-size:13px;margin-top:8px;text-align:right;">{$charCount}/280</div>
</div>
HTML;
}
private static function renderFacebook(string $title, string $text, string $url, string $imageHtml, string $author): string
{
$displayText = !empty($text) ? $text : $title;
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #dddfe2;border-radius:8px;background:#fff;overflow:hidden;">
<div style="padding:12px 16px;">
<div style="display:flex;align-items:center;margin-bottom:8px;">
<div style="width:40px;height:40px;border-radius:50%;background:#1877f2;margin-right:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:bold;font-size:18px;">f</div>
<div>
<div style="font-weight:600;font-size:15px;color:#050505;">{$author}</div>
<div style="color:#65676b;font-size:13px;">Just now</div>
</div>
</div>
<div style="font-size:15px;line-height:1.4;color:#050505;">{$displayText}</div>
</div>
{$imageHtml}
<div style="padding:10px 16px;border-top:1px solid #dddfe2;background:#f0f2f5;">
<div style="font-size:12px;color:#65676b;text-transform:uppercase;">yoursite.com</div>
<div style="font-size:16px;font-weight:600;color:#050505;margin-top:2px;">{$title}</div>
</div>
</div>
HTML;
}
private static function renderMastodon(string $title, string $text, string $url, string $imageHtml, string $author): string
{
$displayText = !empty($text) ? $text : $title;
$charCount = mb_strlen(strip_tags($displayText));
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #c0cdd9;border-radius:8px;padding:14px 16px;background:#fff;">
<div style="display:flex;align-items:center;margin-bottom:10px;">
<div style="width:46px;height:46px;border-radius:8px;background:#6364ff;margin-right:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:bold;font-size:20px;">M</div>
<div>
<div style="font-weight:700;font-size:15px;color:#1a1a2e;">{$author}</div>
<div style="color:#606984;font-size:13px;">@user@mastodon.social</div>
</div>
</div>
<div style="font-size:15px;line-height:1.5;color:#1a1a2e;">{$displayText}</div>
{$imageHtml}
<div style="margin-top:8px;padding:10px 12px;border:1px solid #c0cdd9;border-radius:8px;background:#f2f5f7;">
<div style="font-size:14px;font-weight:600;color:#1a1a2e;">{$title}</div>
<div style="font-size:12px;color:#606984;margin-top:2px;">yoursite.com</div>
</div>
<div style="color:#606984;font-size:13px;margin-top:8px;text-align:right;">{$charCount}/500</div>
</div>
HTML;
}
private static function renderLinkedIn(string $title, string $text, string $url, string $imageHtml, string $author): string
{
$displayText = !empty($text) ? $text : $title;
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #e0dfdc;border-radius:8px;background:#fff;overflow:hidden;">
<div style="padding:12px 16px;">
<div style="display:flex;align-items:center;margin-bottom:8px;">
<div style="width:48px;height:48px;border-radius:50%;background:#0a66c2;margin-right:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:bold;font-size:18px;">in</div>
<div>
<div style="font-weight:600;font-size:14px;color:#191919;">{$author}</div>
<div style="color:#666;font-size:12px;">Just now</div>
</div>
</div>
<div style="font-size:14px;line-height:1.4;color:#191919;">{$displayText}</div>
</div>
{$imageHtml}
<div style="padding:8px 16px 12px;border-top:1px solid #e0dfdc;background:#f9fafb;">
<div style="font-size:14px;font-weight:600;color:#191919;">{$title}</div>
<div style="font-size:12px;color:#666;margin-top:2px;">yoursite.com</div>
</div>
</div>
HTML;
}
private static function renderBluesky(string $title, string $text, string $url, string $imageHtml, string $author): string
{
$displayText = !empty($text) ? $text : $title;
$charCount = mb_strlen(strip_tags($displayText));
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #d1d5db;border-radius:12px;padding:12px 16px;background:#fff;">
<div style="display:flex;align-items:center;margin-bottom:8px;">
<div style="width:42px;height:42px;border-radius:50%;background:#0085ff;margin-right:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:bold;font-size:16px;">B</div>
<div>
<div style="font-weight:600;font-size:15px;color:#1e2937;">{$author}</div>
<div style="color:#6b7280;font-size:13px;">@user.bsky.social</div>
</div>
</div>
<div style="font-size:15px;line-height:1.4;color:#1e2937;">{$displayText}</div>
{$imageHtml}
<div style="margin-top:8px;padding:10px 12px;border:1px solid #d1d5db;border-radius:8px;background:#f9fafb;">
<div style="font-size:14px;font-weight:600;color:#1e2937;">{$title}</div>
<div style="font-size:12px;color:#6b7280;margin-top:2px;">yoursite.com</div>
</div>
<div style="color:#6b7280;font-size:13px;margin-top:8px;text-align:right;">{$charCount}/300</div>
</div>
HTML;
}
private static function renderTelegram(string $title, string $text, string $url, string $imageHtml): string
{
$displayText = !empty($text) ? $text : $title;
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;background:#effdde;border-radius:12px;padding:10px 14px;margin-left:60px;">
{$imageHtml}
<div style="font-size:15px;line-height:1.4;color:#000;">{$displayText}</div>
<div style="margin-top:8px;padding:8px 12px;border-left:3px solid #4fae4e;background:#fff;border-radius:0 8px 8px 0;">
<div style="font-size:14px;font-weight:600;color:#000;">{$title}</div>
<div style="font-size:12px;color:#888;margin-top:2px;">yoursite.com</div>
</div>
<div style="color:#5fb452;font-size:11px;text-align:right;margin-top:4px;">Just now</div>
</div>
HTML;
}
private static function renderGeneric(string $platform, string $title, string $text, string $url, string $imageHtml): string
{
$platformLabel = htmlspecialchars(ucfirst($platform), ENT_QUOTES, 'UTF-8');
$displayText = !empty($text) ? $text : $title;
return <<<HTML
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;max-width:500px;border:1px solid #ddd;border-radius:8px;padding:12px 16px;background:#fff;">
<div style="font-weight:600;font-size:13px;color:#666;margin-bottom:8px;text-transform:uppercase;">{$platformLabel}</div>
<div style="font-size:15px;line-height:1.4;color:#333;">{$displayText}</div>
{$imageHtml}
<div style="margin-top:8px;padding:8px 12px;border:1px solid #ddd;border-radius:6px;background:#f9f9f9;">
<div style="font-size:14px;font-weight:600;color:#333;">{$title}</div>
<div style="font-size:12px;color:#999;">yoursite.com</div>
</div>
</div>
HTML;
}
}
@@ -31,3 +31,6 @@ PLG_CONTENT_MOKOSUITECROSS_SHARE_IMAGE_CUSTOM="Custom Image"
PLG_CONTENT_MOKOSUITECROSS_SHARE_IMAGE_NONE="No Image"
PLG_CONTENT_MOKOSUITECROSS_CUSTOM_IMAGE="Custom Share Image"
PLG_CONTENT_MOKOSUITECROSS_CUSTOM_IMAGE_DESC="Select an image from the media manager to use for cross-posting."
PLG_CONTENT_MOKOSUITECROSS_FIELDSET_PREVIEW="Social Preview"
PLG_CONTENT_MOKOSUITECROSS_PREVIEW="Preview Post"
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="content" method="upgrade">
<name>Content - MokoSuiteCross</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -19,6 +19,7 @@ use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\MokoSuiteCross\Administrator\Helper\CrossPostDispatcher;
use Joomla\Event\SubscriberInterface;
@@ -265,30 +266,57 @@ XML;
$form->load($historyXml);
$form->setFieldAttribute('mokosuitecross_history', 'description', $historyHtml, 'attribs');
}
// Social Preview panel (#156)
$token = Session::getFormToken();
$previewUrl = Uri::base() . 'index.php?option=com_mokosuitecross&task=preview.render&format=raw&article_id=' . $articleId . '&' . $token . '=1';
$previewButtonHtml = '<div id="mokosuitecross-preview-panel">'
. '<div class="mb-2">'
. '<select id="mokosuitecross-preview-platform" class="form-select form-select-sm" style="width:auto;display:inline-block;">'
. '<option value="all">All Platforms</option>'
. '<option value="twitter">X / Twitter</option>'
. '<option value="facebook">Facebook</option>'
. '<option value="linkedin">LinkedIn</option>'
. '<option value="mastodon">Mastodon</option>'
. '<option value="bluesky">Bluesky</option>'
. '<option value="telegram">Telegram</option>'
. '</select> '
. '<button type="button" class="btn btn-sm btn-outline-primary" onclick="mokosuitecrossLoadPreview()">'
. '<span class="icon-eye" aria-hidden="true"></span> Preview</button>'
. '</div>'
. '<div id="mokosuitecross-preview-output" style="max-height:600px;overflow-y:auto;"></div>'
. '</div>'
. '<script>'
. 'function mokosuitecrossLoadPreview(){'
. 'var p=document.getElementById("mokosuitecross-preview-platform").value;'
. 'var o=document.getElementById("mokosuitecross-preview-output");'
. 'o.innerHTML="<div class=\"text-center p-3\"><span class=\"spinner-border spinner-border-sm\"></span> Loading...</div>";'
. 'fetch("' . $previewUrl . '&platform="+p)'
. '.then(function(r){return r.text();})'
. '.then(function(h){o.innerHTML=h;})'
. '.catch(function(){o.innerHTML="<div class=\"alert alert-danger\">Preview failed</div>";});'
. '}'
. '</script>';
$previewXml = '<?xml version="1.0"?>
<form><fields name="attribs"><fieldset name="mokosuitecross_preview" label="PLG_CONTENT_MOKOSUITECROSS_FIELDSET_PREVIEW">
<field name="mokosuitecross_preview_panel" type="note"
label="PLG_CONTENT_MOKOSUITECROSS_PREVIEW"
description="" />
</fieldset></fields></form>';
$form->load($previewXml);
$form->setFieldAttribute('mokosuitecross_preview_panel', 'description', $previewButtonHtml, 'attribs');
}
}
/**
* Add cross-post status badges before article content in admin.
*
* Joomla 5/6 compatible — accepts both BeforeDisplayEvent and legacy parameters.
*/
public function onContentBeforeDisplay($event): string
public function onContentBeforeDisplay(\Joomla\CMS\Event\Content\BeforeDisplayEvent $event): string
{
// Joomla 5/6 compatibility
if ($event instanceof \Joomla\CMS\Event\Content\BeforeDisplayEvent) {
$context = $event->getContext();
$article = $event->getItem();
} elseif (is_string($event)) {
$context = $event;
$article = func_get_arg(1);
} else {
return '';
}
if ($context !== 'com_content.article') {
return '';
}
$context = $event->getContext();
$article = $event->getItem();
$app = $this->getApplication();
@@ -330,26 +358,18 @@ XML;
/**
* Dispatch cross-post when an article is saved and published.
*
* Joomla 5/6 compatible — accepts both AfterSaveEvent and legacy parameters.
*/
public function onContentAfterSave($event): void
public function onContentAfterSave(\Joomla\CMS\Event\Content\AfterSaveEvent $event): void
{
// Joomla 5/6 compatibility
if ($event instanceof \Joomla\CMS\Event\Content\AfterSaveEvent) {
$context = $event->getContext();
$article = $event->getItem();
$isNew = $event->getIsNew();
} else {
$context = $event;
$article = func_get_arg(1);
$isNew = func_get_arg(2);
}
$context = $event->getContext();
if ($context !== 'com_content.article') {
return;
}
$article = $event->getItem();
$isNew = $event->getIsNew();
if ((int) ($article->state ?? 0) !== 1) {
return;
}
@@ -375,25 +395,18 @@ XML;
/**
* Dispatch cross-post when article state changes to published.
*
* Joomla 5/6 compatible — accepts both ContentChangeStateEvent and legacy parameters.
*/
public function onContentChangeState($event): void
public function onContentChangeState(\Joomla\CMS\Event\Content\ContentChangeStateEvent $event): void
{
if ($event instanceof \Joomla\CMS\Event\Content\ContentChangeStateEvent) {
$context = $event->getContext();
$pks = $event->getPks();
$value = $event->getValue();
} else {
$context = $event;
$pks = func_get_arg(1);
$value = func_get_arg(2);
}
$context = $event->getContext();
if ($context !== 'com_content.article') {
return;
}
$pks = $event->getPks();
$value = $event->getValue();
$params = ComponentHelper::getParams('com_mokosuitecross');
// Unpublish/trash: delete from platforms if configured
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - ActivityPub (Fediverse)</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Blogger</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Bluesky</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Brevo (Sendinblue)</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Constant Contact</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - ConvertKit</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Dev.to</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Discord</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Facebook / Meta</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Ghost</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Business Profile</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Chat</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Hashnode</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Instagram</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-06-23</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - LinkedIn</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Mailchimp</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Mastodon</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Matrix / Element</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Medium</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - MokoSuiteCalendar Events</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - MokoSuiteGallery</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Nostr</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Ntfy Push Notifications</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Pinterest</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Reddit</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - RSS Feed</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - SendGrid</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Slack</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Microsoft Teams</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Telegram</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Threads (Meta)</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - TikTok</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Tumblr</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - X / Twitter</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Generic Webhook</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - WhatsApp Business</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - WordPress</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Youtube</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-06-23</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross Events</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross Gallery</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="task" method="upgrade">
<name>Task - MokoSuiteCross Queue Processor</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="webservices" method="upgrade">
<name>Web Services - MokoSuiteCross</name>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -35,8 +35,9 @@ class MokoSuiteCrossWebServices extends CMSPlugin implements SubscriberInterface
];
}
public function onBeforeApiRoute(&$router): void
public function onBeforeApiRoute($event): void
{
$router = $event instanceof \Joomla\CMS\Event\AbstractEvent ? $event->getRouter() : $event;
$defaults = ['component' => 'com_mokosuitecross'];
$router->createCRUDRoutes('v1/mokosuitecross/posts', 'posts', $defaults);
@@ -44,7 +45,6 @@ class MokoSuiteCrossWebServices extends CMSPlugin implements SubscriberInterface
$router->createCRUDRoutes('v1/mokosuitecross/templates', 'templates', $defaults);
$router->createCRUDRoutes('v1/mokosuitecross/logs', 'logs', $defaults);
// Action endpoint: dispatch cross-posts for an article (POST only)
$router->addRoute(
new \Joomla\Router\Route(['POST'], 'v1/mokosuitecross/dispatch', 'dispatch.dispatch', [], $defaults)
);
+1 -1
View File
@@ -2,7 +2,7 @@
<extension type="package" method="upgrade">
<name>MokoSuiteCross</name>
<packagename>mokosuitecross</packagename>
<version>01.08.00</version>
<version>01.08.11</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>