Release 02.01.20 — brand buttons, dev mode, ATS overrides #4
@@ -58,7 +58,7 @@ permissions:
|
||||
jobs:
|
||||
release:
|
||||
name: Build & Release Pipeline
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: release
|
||||
if: >-
|
||||
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
||||
|
||||
@@ -75,6 +75,10 @@ jobs:
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
run: |
|
||||
# Ensure PHP + Composer are available
|
||||
if ! command -v composer &> /dev/null; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
|
||||
fi
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||
/tmp/mokostandards-api
|
||||
@@ -564,7 +568,6 @@ jobs:
|
||||
new_downloads = (
|
||||
" <downloads>\n"
|
||||
f" <downloadurl type=\"full\" format=\"zip\">{zip_url}</downloadurl>\n"
|
||||
f" <downloadurl type=\"full\" format=\"tar.gz\">{tar_url}</downloadurl>\n"
|
||||
" </downloads>"
|
||||
)
|
||||
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
|
||||
@@ -592,69 +595,29 @@ jobs:
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
||||
git push || true
|
||||
|
||||
# Sync updates.xml to main via PR (respects branch protection)
|
||||
if [ "$CURRENT_BRANCH" != "main" ]; then
|
||||
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
|
||||
PR_BRANCH="chore/update-xml-${VERSION}"
|
||||
# Sync updates.xml to main via direct API (always runs — may be on version/XX branch)
|
||||
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
|
||||
|
||||
# Create branch from main
|
||||
MAIN_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/branches/main" | jq -r '.commit.sha // empty')
|
||||
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty')
|
||||
|
||||
if [ -n "$MAIN_SHA" ]; then
|
||||
curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/branches" \
|
||||
-d "$(jq -n --arg name "$PR_BRANCH" --arg sha "$MAIN_SHA" \
|
||||
'{new_branch_name: $name, old_branch_name: "main"}')" > /dev/null 2>&1 || true
|
||||
|
||||
# Update updates.xml on the PR branch
|
||||
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=${PR_BRANCH}" | jq -r '.sha // empty')
|
||||
|
||||
if [ -n "$FILE_SHA" ]; then
|
||||
CONTENT=$(base64 -w0 updates.xml)
|
||||
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/contents/updates.xml" \
|
||||
-d "$(jq -n \
|
||||
--arg content "$CONTENT" \
|
||||
--arg sha "$FILE_SHA" \
|
||||
--arg msg "chore: update stable channel to ${VERSION} [skip ci]" \
|
||||
--arg branch "$PR_BRANCH" \
|
||||
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
|
||||
)" > /dev/null 2>&1
|
||||
|
||||
# Create PR
|
||||
PR_URL=$(curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/pulls" \
|
||||
-d "$(jq -n \
|
||||
--arg title "chore: update updates.xml for ${VERSION} [skip ci]" \
|
||||
--arg head "$PR_BRANCH" \
|
||||
--arg base "main" \
|
||||
--arg body "Auto-generated by release workflow. Updates updates.xml with SHA-256 and download URLs for ${VERSION}." \
|
||||
'{title: $title, head: $head, base: $base, body: $body}'
|
||||
)" | jq -r '.number // empty')
|
||||
|
||||
# Auto-merge the PR
|
||||
if [ -n "$PR_URL" ]; then
|
||||
curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/pulls/${PR_URL}/merge" \
|
||||
-d '{"Do":"merge","merge_message_field":"chore: update updates.xml for '"${VERSION}"' [skip ci]"}' > /dev/null 2>&1 \
|
||||
&& echo "updates.xml synced to main via PR #${PR_URL}" \
|
||||
|| echo "PR #${PR_URL} created but auto-merge failed — merge manually"
|
||||
|
||||
# Cleanup: delete PR branch
|
||||
curl -sf -X DELETE -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/branches/${PR_BRANCH}" > /dev/null 2>&1 || true
|
||||
else
|
||||
echo "WARNING: failed to create PR for updates.xml sync"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ -n "$FILE_SHA" ]; then
|
||||
CONTENT=$(base64 -w0 updates.xml)
|
||||
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/contents/updates.xml" \
|
||||
-d "$(jq -n \
|
||||
--arg content "$CONTENT" \
|
||||
--arg sha "$FILE_SHA" \
|
||||
--arg msg "chore: sync updates.xml ${VERSION} [skip ci]" \
|
||||
--arg branch "main" \
|
||||
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
|
||||
)" > /dev/null 2>&1 \
|
||||
&& echo "updates.xml synced to main via API" \
|
||||
|| echo "WARNING: failed to sync updates.xml to main"
|
||||
else
|
||||
echo "WARNING: could not get updates.xml SHA from main"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Update MokoCassiopeia Payload
|
||||
name: Update MokoOnyx Payload
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -14,25 +14,25 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get latest MokoCassiopeia release URL
|
||||
- name: Get latest MokoOnyx stable release URL
|
||||
id: moko
|
||||
run: |
|
||||
DOWNLOAD_URL=$(curl -s https://api.github.com/repos/mokoconsulting-tech/MokoCassiopeia/releases \
|
||||
| jq -r '[.[] | select(.prerelease == false and .draft == false and (.assets | length > 0)][0].assets[0].browser_download_url')
|
||||
DOWNLOAD_URL=$(curl -s https://git.mokoconsulting.tech/api/v1/repos/MokoConsulting/MokoOnyx/releases \
|
||||
| jq -r '[.[] | select(.prerelease == false and .draft == false and (.assets | length > 0))][0].assets[0].browser_download_url')
|
||||
echo "url=$DOWNLOAD_URL" >> $GITHUB_OUTPUT
|
||||
echo "Found: $DOWNLOAD_URL"
|
||||
|
||||
- name: Download MokoCassiopeia zip
|
||||
- name: Download MokoOnyx zip
|
||||
if: steps.moko.outputs.url != 'null'
|
||||
run: |
|
||||
mkdir -p src/payload
|
||||
curl -sL "${{ steps.moko.outputs.url }}" -o src/payload/mokocassiopeia.zip
|
||||
curl -sL "${{ steps.moko.outputs.url }}" -o src/payload/mokoonyx.zip
|
||||
ls -la src/payload/
|
||||
|
||||
- name: Check if payload changed
|
||||
id: diff
|
||||
run: |
|
||||
git add src/payload/mokocassiopeia.zip
|
||||
git add src/payload/mokoonyx.zip
|
||||
if git diff --cached --quiet; then
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
@@ -44,5 +44,5 @@ jobs:
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git commit -m "chore: update mokocassiopeia payload"
|
||||
git commit -m "chore: update mokoonyx payload"
|
||||
git push
|
||||
|
||||
@@ -13,16 +13,27 @@
|
||||
# Writes updates.xml with multiple <update> entries:
|
||||
# - <tag>stable</tag> on push to main (from auto-release)
|
||||
# - <tag>rc</tag> on push to rc/**
|
||||
# - <tag>development</tag> on push to dev/**
|
||||
# - <tag>development</tag> on push to dev or dev/**
|
||||
#
|
||||
# Joomla filters by user's "Minimum Stability" setting.
|
||||
|
||||
name: Update Joomla Update Server XML Feed
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'dev'
|
||||
- 'dev/**'
|
||||
- 'alpha/**'
|
||||
- 'beta/**'
|
||||
- 'rc/**'
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'htdocs/**'
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
- 'dev'
|
||||
- 'dev/**'
|
||||
- 'alpha/**'
|
||||
- 'beta/**'
|
||||
@@ -56,9 +67,9 @@ permissions:
|
||||
jobs:
|
||||
update-xml:
|
||||
name: Update updates.xml
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: release
|
||||
if: >-
|
||||
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
||||
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' || github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -73,6 +84,9 @@ jobs:
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
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
|
||||
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
|
||||
@@ -109,7 +123,7 @@ jobs:
|
||||
STABILITY="beta"
|
||||
elif [[ "$BRANCH" == alpha/* ]]; then
|
||||
STABILITY="alpha"
|
||||
elif [[ "$BRANCH" == dev/* ]]; then
|
||||
elif [[ "$BRANCH" == dev/* ]] || [[ "$BRANCH" == "dev" ]]; then
|
||||
STABILITY="development"
|
||||
else
|
||||
STABILITY="stable"
|
||||
@@ -271,9 +285,7 @@ jobs:
|
||||
NEW_ENTRY="${NEW_ENTRY} </tags>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloads>\n"
|
||||
TAR_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${EXT_ELEMENT}-${DISPLAY_VERSION}.tar.gz"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} </downloads>\n"
|
||||
[ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} <sha256>${SHA256}</sha256>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} ${TARGET_PLATFORM}\n"
|
||||
@@ -367,6 +379,33 @@ jobs:
|
||||
git push
|
||||
}
|
||||
|
||||
# -- Sync updates.xml to main (for non-main branches) ----------------------
|
||||
- name: Sync updates.xml to main
|
||||
if: github.ref_name != 'main'
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
|
||||
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API_BASE}/contents/updates.xml?ref=main" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$FILE_SHA" ] && [ -f "updates.xml" ]; then
|
||||
CONTENT=$(base64 -w0 updates.xml)
|
||||
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/contents/updates.xml" \
|
||||
-d "$(python3 -c "import json; print(json.dumps({
|
||||
'content': '${CONTENT}',
|
||||
'sha': '${FILE_SHA}',
|
||||
'message': 'chore: sync updates.xml from ${STABILITY} [skip ci]',
|
||||
'branch': 'main'
|
||||
}))")" > /dev/null 2>&1 \
|
||||
&& echo "updates.xml synced to main (${STABILITY})" >> $GITHUB_STEP_SUMMARY \
|
||||
|| echo "WARNING: failed to sync updates.xml to main" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "WARNING: could not get updates.xml SHA from main" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# -- Mirror to GitHub (stable and rc only) --------------------------------
|
||||
- name: Mirror release to GitHub
|
||||
if: >-
|
||||
@@ -388,7 +427,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: SFTP deploy to dev server
|
||||
if: contains(github.ref, 'dev/')
|
||||
if: contains(github.ref, 'dev/') || github.ref == 'refs/heads/dev'
|
||||
env:
|
||||
DEV_HOST: ${{ vars.DEV_FTP_HOST }}
|
||||
DEV_PATH: ${{ vars.DEV_FTP_PATH }}
|
||||
|
||||
@@ -9,6 +9,8 @@ TODO.md
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.joomla-api-mcp.json
|
||||
.mcp.json
|
||||
*.local.php
|
||||
*.secret.php
|
||||
configuration.php
|
||||
@@ -100,6 +102,7 @@ replit.md
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
!src/payload/*.zip
|
||||
artifacts/
|
||||
release/
|
||||
releases/
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
DEFGROUP: Joomla.Plugin
|
||||
INGROUP: MokoWaaS
|
||||
REPO: https://github.com/mokoconsulting-tech/mokowaas
|
||||
VERSION: 02.01.15
|
||||
VERSION: 02.01.20
|
||||
PATH: /README.md
|
||||
BRIEF: Rebranding plugin for MokoWaaS platform
|
||||
NOTE: Internal WaaS identity abstraction layer
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
# MokoWaaS Plugin
|
||||
|
||||
[](https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/v02)
|
||||
[](https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/v02)
|
||||
[](LICENSE)
|
||||
[](https://www.joomla.org)
|
||||
[](https://www.php.net)
|
||||
@@ -322,22 +322,18 @@ See [LICENSE.md](LICENSE.md) for the full license text.
|
||||
|
||||
This extension follows the [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) version governance model using semantic versioning: `MAJOR.MINOR.PATCH`
|
||||
|
||||
Current version: **01.04.00**
|
||||
Current version: **02.01.18**
|
||||
|
||||
## Changelog
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md) for a complete version history.
|
||||
|
||||
### Recent Changes (v01.04.00 - 2026-02-22)
|
||||
### Recent Changes (v02.01.18 - 2026-04-23)
|
||||
|
||||
- Added complete Joomla 5.x system plugin implementation
|
||||
- Created main plugin class with event handlers
|
||||
- Implemented plugin manifest with Joomla 5.x namespace support
|
||||
- Added dependency injection service provider
|
||||
- Created plugin language files
|
||||
- Integrated with language override system
|
||||
- Enhanced language overrides (57+ strings)
|
||||
- Fixed typo in error messages (OCCURRED)
|
||||
- Always install and lock MokoOnyx template on install/update
|
||||
- Always unlock MokoCassiopeia on install/update (allow uninstall)
|
||||
- Bundle MokoOnyx payload (replaces MokoCassiopeia payload)
|
||||
- Update payload workflow to fetch MokoOnyx from Gitea releases
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -80,6 +80,9 @@ class MokoWaaS extends CMSPlugin
|
||||
// Security: HTTPS redirect (runs for all clients)
|
||||
$this->enforceHttps();
|
||||
|
||||
// Dev mode: disable caching
|
||||
$this->enforceDevMode();
|
||||
|
||||
// Admin-only WaaS controls
|
||||
if ($this->app->isClient('administrator'))
|
||||
{
|
||||
@@ -965,6 +968,27 @@ class MokoWaaS extends CMSPlugin
|
||||
*
|
||||
* @since 02.01.08
|
||||
*/
|
||||
/**
|
||||
* Disable caching when development mode is active.
|
||||
*
|
||||
* Sets the Joomla caching config to 0 at runtime so no page
|
||||
* or component cache is used. Does not modify configuration.php.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 02.01.15
|
||||
*/
|
||||
protected function enforceDevMode()
|
||||
{
|
||||
if (!$this->params->get('dev_mode', 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$config = Factory::getConfig();
|
||||
$config->set('caching', 0);
|
||||
}
|
||||
|
||||
protected function enforceHttps()
|
||||
{
|
||||
if (!$this->params->get('force_https', 0))
|
||||
@@ -1529,8 +1553,78 @@ class MokoWaaS extends CMSPlugin
|
||||
*/
|
||||
protected function injectColorScheme($doc)
|
||||
{
|
||||
// Colors are applied via Atum template style params in
|
||||
// enforceAtumBranding(). No additional CSS injection needed.
|
||||
$primary = $this->params->get('color_primary', '');
|
||||
$brandIcon = $this->params->get('brand_icon', '');
|
||||
$css = '';
|
||||
|
||||
// Brand button colors derived from primary color
|
||||
if (!empty($primary))
|
||||
{
|
||||
$primary = htmlspecialchars($primary, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$css .= '.btn-primary,'
|
||||
. '.btn-primary:not(:disabled):not(.disabled){'
|
||||
. 'background-color:' . $primary . ';'
|
||||
. 'border-color:' . $primary . ';'
|
||||
. 'color:#000;'
|
||||
. 'box-shadow:0 2px 4px rgba(0,0,0,.15);}'
|
||||
. '.btn-primary:hover,.btn-primary:focus{'
|
||||
. 'background-color:' . $primary . ';'
|
||||
. 'border-color:' . $primary . ';'
|
||||
. 'color:#000;'
|
||||
. 'filter:brightness(0.85);'
|
||||
. 'box-shadow:0 4px 8px rgba(0,0,0,.2);}'
|
||||
. '.btn-primary:active,.btn-primary.active{'
|
||||
. 'background-color:' . $primary . ';'
|
||||
. 'border-color:' . $primary . ';'
|
||||
. 'color:#000;'
|
||||
. 'filter:brightness(0.75);}'
|
||||
. '.btn-outline-primary{'
|
||||
. 'color:' . $primary . ';'
|
||||
. 'border-color:' . $primary . ';'
|
||||
. 'border-width:2px;}'
|
||||
. '.btn-outline-primary:hover,.btn-outline-primary:focus{'
|
||||
. 'background-color:' . $primary . ';'
|
||||
. 'border-color:' . $primary . ';'
|
||||
. 'color:#000;}';
|
||||
}
|
||||
|
||||
// Drawer toggle button: flat edge on the sidebar-facing side
|
||||
// Close button in drawer: styled to match brand
|
||||
$css .= '[dir="ltr"] .main-nav-container .menu-collapse,'
|
||||
. '[dir="ltr"] .sidebar-toggle{'
|
||||
. 'border-top-left-radius:0!important;'
|
||||
. 'border-bottom-left-radius:0!important;}'
|
||||
. '[dir="rtl"] .main-nav-container .menu-collapse,'
|
||||
. '[dir="rtl"] .sidebar-toggle{'
|
||||
. 'border-top-right-radius:0!important;'
|
||||
. 'border-bottom-right-radius:0!important;}'
|
||||
. '.sidebar-wrapper .btn-close,'
|
||||
. '.sidebar-wrapper [data-bs-dismiss]{'
|
||||
. 'opacity:1;'
|
||||
. 'filter:none;'
|
||||
. 'font-size:1.1rem;}';
|
||||
|
||||
// Brand icon override (FontAwesome unicode codepoint)
|
||||
if (!empty($brandIcon))
|
||||
{
|
||||
$brandIcon = preg_replace('/[^a-fA-F0-9]/', '', $brandIcon);
|
||||
|
||||
if (!empty($brandIcon))
|
||||
{
|
||||
$css .= '.icon-joomla::before,'
|
||||
. '.icon-brands.fa-joomla::before{'
|
||||
. 'font-family:"Font Awesome 6 Free"!important;'
|
||||
. 'content:"\\' . $brandIcon . '"!important;'
|
||||
. 'font-weight:900!important;}';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty(trim($css)))
|
||||
{
|
||||
$css = str_replace('</style>', '', $css);
|
||||
$doc->addStyleDeclaration($css);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -107,3 +107,14 @@ JLIB_INSTALLER_ERROR_NOTFINDJOOMLAXMLSETUPFILE="Installer: Can't find {{BRAND_NA
|
||||
JLIB_HTML_POWERED_BY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
COM_ADMIN_HELP_DOCUMENTATION="{{BRAND_NAME}} Documentation"
|
||||
COM_ADMIN_HELP_SUPPORT="{{BRAND_NAME}} Support"
|
||||
|
||||
; ===== Akeeba Ticket System (ATS) =====
|
||||
COM_ATS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKETS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKET="{{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_NEWTICKET="New {{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_CATEGORIES="Ticket Categories"
|
||||
COM_ATS_MSG_TICKET_SAVED="Your {{BRAND_NAME}} ticket has been saved."
|
||||
COM_ATS_MSG_TICKET_CLOSED="Your {{BRAND_NAME}} ticket has been closed."
|
||||
COM_ATS_MSG_REPLY_SAVED="Your reply has been saved."
|
||||
COM_ATS_LBL_POWEREDBY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
@@ -107,3 +107,14 @@ JLIB_INSTALLER_ERROR_NOTFINDJOOMLAXMLSETUPFILE="Installer: Can't find {{BRAND_NA
|
||||
JLIB_HTML_POWERED_BY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
COM_ADMIN_HELP_DOCUMENTATION="{{BRAND_NAME}} Documentation"
|
||||
COM_ADMIN_HELP_SUPPORT="{{BRAND_NAME}} Support"
|
||||
|
||||
; ===== Akeeba Ticket System (ATS) =====
|
||||
COM_ATS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKETS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKET="{{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_NEWTICKET="New {{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_CATEGORIES="Ticket Categories"
|
||||
COM_ATS_MSG_TICKET_SAVED="Your {{BRAND_NAME}} ticket has been saved."
|
||||
COM_ATS_MSG_TICKET_CLOSED="Your {{BRAND_NAME}} ticket has been closed."
|
||||
COM_ATS_MSG_REPLY_SAVED="Your reply has been saved."
|
||||
COM_ATS_LBL_POWEREDBY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
@@ -55,6 +55,9 @@ PLG_SYSTEM_MOKOWAAS_ALLOWED_IPS_NOTE_DESC="Emergency access requires an IP white
|
||||
PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_LABEL="Maintenance"
|
||||
PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_DESC="One-time maintenance actions. Set to Yes and save to execute. Resets to No automatically after execution."
|
||||
|
||||
PLG_SYSTEM_MOKOWAAS_DEV_MODE_LABEL="Development Mode"
|
||||
PLG_SYSTEM_MOKOWAAS_DEV_MODE_DESC="Disables all Joomla caching at runtime. Useful during development and testing. Does not modify configuration.php."
|
||||
|
||||
PLG_SYSTEM_MOKOWAAS_RESET_HITS_LABEL="Reset All Hits"
|
||||
PLG_SYSTEM_MOKOWAAS_RESET_HITS_DESC="Set all article hit counters to zero across the site. This action executes on save and resets to No."
|
||||
PLG_SYSTEM_MOKOWAAS_DELETE_VERSIONS_LABEL="Delete All Versions"
|
||||
@@ -74,6 +77,8 @@ PLG_SYSTEM_MOKOWAAS_COLOR_HEADER_LABEL="Header Color"
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_HEADER_DESC="Background color for the admin top header bar."
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_LINK_LABEL="Link Color"
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_LINK_DESC="Color for hyperlinks in the admin interface."
|
||||
PLG_SYSTEM_MOKOWAAS_BRAND_ICON_LABEL="Brand Icon (FontAwesome)"
|
||||
PLG_SYSTEM_MOKOWAAS_BRAND_ICON_DESC="FontAwesome unicode codepoint for the brand icon that replaces the Joomla logo icon. Enter the hex code only (e.g. f6d5 for fa-hat-cowboy). Find codes at fontawesome.com/icons."
|
||||
PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_LABEL="Custom CSS"
|
||||
PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_DESC="Additional CSS injected into admin pages. Use for fine-tuning visual presentation."
|
||||
|
||||
|
||||
@@ -55,6 +55,9 @@ PLG_SYSTEM_MOKOWAAS_ALLOWED_IPS_NOTE_DESC="Emergency access requires an IP white
|
||||
PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_LABEL="Maintenance"
|
||||
PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_DESC="One-time maintenance actions. Set to Yes and save to execute. Resets to No automatically after execution."
|
||||
|
||||
PLG_SYSTEM_MOKOWAAS_DEV_MODE_LABEL="Development Mode"
|
||||
PLG_SYSTEM_MOKOWAAS_DEV_MODE_DESC="Disables all Joomla caching at runtime. Useful during development and testing. Does not modify configuration.php."
|
||||
|
||||
PLG_SYSTEM_MOKOWAAS_RESET_HITS_LABEL="Reset All Hits"
|
||||
PLG_SYSTEM_MOKOWAAS_RESET_HITS_DESC="Set all article hit counters to zero across the site. This action executes on save and resets to No."
|
||||
PLG_SYSTEM_MOKOWAAS_DELETE_VERSIONS_LABEL="Delete All Versions"
|
||||
@@ -74,6 +77,8 @@ PLG_SYSTEM_MOKOWAAS_COLOR_HEADER_LABEL="Header Color"
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_HEADER_DESC="Background color for the admin top header bar."
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_LINK_LABEL="Link Color"
|
||||
PLG_SYSTEM_MOKOWAAS_COLOR_LINK_DESC="Color for hyperlinks in the admin interface."
|
||||
PLG_SYSTEM_MOKOWAAS_BRAND_ICON_LABEL="Brand Icon (FontAwesome)"
|
||||
PLG_SYSTEM_MOKOWAAS_BRAND_ICON_DESC="FontAwesome unicode codepoint for the brand icon that replaces the Joomla logo icon. Enter the hex code only (e.g. f6d5 for fa-hat-cowboy). Find codes at fontawesome.com/icons."
|
||||
PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_LABEL="Custom CSS"
|
||||
PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_DESC="Additional CSS injected into admin pages. Use for fine-tuning visual presentation."
|
||||
|
||||
|
||||
@@ -53,3 +53,14 @@ JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND="Component not found."
|
||||
|
||||
; ===== Version and About =====
|
||||
JLIB_HTML_POWERED_BY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
; ===== Akeeba Ticket System (ATS) =====
|
||||
COM_ATS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKETS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKET="{{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_NEWTICKET="New {{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_CATEGORIES="Ticket Categories"
|
||||
COM_ATS_MSG_TICKET_SAVED="Your {{BRAND_NAME}} ticket has been saved."
|
||||
COM_ATS_MSG_TICKET_CLOSED="Your {{BRAND_NAME}} ticket has been closed."
|
||||
COM_ATS_MSG_REPLY_SAVED="Your reply has been saved."
|
||||
COM_ATS_LBL_POWEREDBY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
@@ -53,3 +53,14 @@ JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND="Component not found."
|
||||
|
||||
; ===== Version and About =====
|
||||
JLIB_HTML_POWERED_BY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
; ===== Akeeba Ticket System (ATS) =====
|
||||
COM_ATS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKETS="{{BRAND_NAME}} Tickets"
|
||||
COM_ATS_TITLE_TICKET="{{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_NEWTICKET="New {{BRAND_NAME}} Ticket"
|
||||
COM_ATS_TITLE_CATEGORIES="Ticket Categories"
|
||||
COM_ATS_MSG_TICKET_SAVED="Your {{BRAND_NAME}} ticket has been saved."
|
||||
COM_ATS_MSG_TICKET_CLOSED="Your {{BRAND_NAME}} ticket has been closed."
|
||||
COM_ATS_MSG_REPLY_SAVED="Your reply has been saved."
|
||||
COM_ATS_LBL_POWEREDBY="Powered by <a href='{{SUPPORT_URL}}'>{{BRAND_NAME}}</a>"
|
||||
|
||||
@@ -162,6 +162,13 @@
|
||||
label="PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_FIELDSET_MAINTENANCE_DESC"
|
||||
>
|
||||
<field name="dev_mode" type="radio" default="0"
|
||||
label="PLG_SYSTEM_MOKOWAAS_DEV_MODE_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_DEV_MODE_DESC"
|
||||
class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field
|
||||
name="reset_hits"
|
||||
type="radio"
|
||||
@@ -209,6 +216,10 @@
|
||||
label="PLG_SYSTEM_MOKOWAAS_COLOR_LINK_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_COLOR_LINK_DESC"
|
||||
default="#0051ad" />
|
||||
<field name="brand_icon" type="text"
|
||||
label="PLG_SYSTEM_MOKOWAAS_BRAND_ICON_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_BRAND_ICON_DESC"
|
||||
default="" hint="e.g. f6d5 (FontAwesome unicode)" />
|
||||
<field name="custom_css" type="textarea"
|
||||
label="PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_CUSTOM_CSS_DESC"
|
||||
|
||||
Binary file not shown.
+42
-60
@@ -210,11 +210,11 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the active Moko template is installed and locked.
|
||||
* Ensure MokoOnyx is installed, locked, and set as default.
|
||||
*
|
||||
* Prefers MokoOnyx (successor). Falls back to MokoCassiopeia.
|
||||
* If MokoOnyx is found, lock it and unlock MokoCassiopeia.
|
||||
* If only MokoCassiopeia is found, lock it as before.
|
||||
* Always installs MokoOnyx from bundled payload if not present,
|
||||
* locks it, sets it as default site template, and unlocks
|
||||
* MokoCassiopeia so it can be uninstalled.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
@@ -224,14 +224,23 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Check for MokoOnyx first (successor template)
|
||||
// Check whether MokoOnyx is already installed
|
||||
$query = $db->getQuery(true)
|
||||
->select([$db->quoteName('extension_id'), $db->quoteName('enabled')])
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokoonyx'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'));
|
||||
$onyx = $db->setQuery($query)->loadObject();
|
||||
|
||||
// Install from payload if missing
|
||||
if (!$onyx)
|
||||
{
|
||||
$this->installMokoOnyxFromPayload();
|
||||
|
||||
// Re-check after install
|
||||
$onyx = $db->setQuery($query)->loadObject();
|
||||
}
|
||||
|
||||
if ($onyx)
|
||||
{
|
||||
// Lock and protect MokoOnyx
|
||||
@@ -245,73 +254,49 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
)->execute();
|
||||
|
||||
$this->setDefaultTemplate('mokoonyx', 0);
|
||||
|
||||
// Unlock MokoCassiopeia if present (allow uninstall)
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('locked') . ' = 0')
|
||||
->set($db->quoteName('protected') . ' = 0')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
)->execute();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: MokoCassiopeia
|
||||
$query = $db->getQuery(true)
|
||||
->select([$db->quoteName('extension_id'), $db->quoteName('enabled')])
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'));
|
||||
$template = $db->setQuery($query)->loadObject();
|
||||
// Always unlock MokoCassiopeia (allow uninstall)
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('locked') . ' = 0')
|
||||
->set($db->quoteName('protected') . ' = 0')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('mokocassiopeia'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
)->execute();
|
||||
}
|
||||
|
||||
if ($template)
|
||||
{
|
||||
// Lock, protect, and set as default
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->update($db->quoteName('#__extensions'))
|
||||
->set($db->quoteName('enabled') . ' = 1')
|
||||
->set($db->quoteName('locked') . ' = 1')
|
||||
->set($db->quoteName('protected') . ' = 1')
|
||||
->where($db->quoteName('extension_id') . ' = '
|
||||
. (int) $template->extension_id)
|
||||
);
|
||||
$db->execute();
|
||||
|
||||
$this->setDefaultTemplate('mokocassiopeia', 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Template not installed — install from bundled payload
|
||||
/**
|
||||
* Install MokoOnyx from the bundled payload zip.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 02.01.17
|
||||
*/
|
||||
private function installMokoOnyxFromPayload()
|
||||
{
|
||||
$pluginPath = JPATH_PLUGINS . '/system/mokowaas';
|
||||
$payloadZip = $pluginPath . '/payload/mokocassiopeia.zip';
|
||||
$payloadZip = $pluginPath . '/payload/mokoonyx.zip';
|
||||
|
||||
if (!file_exists($payloadZip))
|
||||
{
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoCassiopeia payload not found at '
|
||||
. $payloadZip,
|
||||
'MokoOnyx payload not found. Please install MokoOnyx manually from '
|
||||
. '<a href="https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases" target="_blank">Gitea Releases</a>.',
|
||||
'warning'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$tmpDir = JPATH_ROOT . '/tmp/mokocassiopeia';
|
||||
$tmpDir = JPATH_ROOT . '/tmp/mokoonyx';
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Extract the bundled zip
|
||||
$archive = new \Joomla\Archive\Archive();
|
||||
$archive->extract($payloadZip, $tmpDir);
|
||||
|
||||
// Release zips should have templateDetails.xml at root
|
||||
// or one level deep
|
||||
$installDir = $tmpDir;
|
||||
|
||||
if (!file_exists($tmpDir . '/templateDetails.xml'))
|
||||
@@ -325,8 +310,7 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
else
|
||||
{
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoCassiopeia: templateDetails.xml not '
|
||||
. 'found in archive.',
|
||||
'MokoOnyx: templateDetails.xml not found in archive.',
|
||||
'warning'
|
||||
);
|
||||
|
||||
@@ -338,17 +322,15 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
|
||||
if ($installer->install($installDir))
|
||||
{
|
||||
$this->ensureMokoCassiopeia();
|
||||
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoCassiopeia installed and locked.',
|
||||
'MokoOnyx installed successfully.',
|
||||
'message'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoCassiopeia installation failed.',
|
||||
'MokoOnyx installation from payload failed.',
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
@@ -356,7 +338,7 @@ class plgSystemMokoWaaSInstallerScript implements InstallerScriptInterface
|
||||
catch (\Exception $e)
|
||||
{
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
'MokoCassiopeia error: ' . $e->getMessage(),
|
||||
'MokoOnyx error: ' . $e->getMessage(),
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
|
||||
+3
-4
@@ -11,7 +11,7 @@
|
||||
<description>System - MokoWaaS (development)</description>
|
||||
<element>mokowaas</element>
|
||||
<type>plugin</type>
|
||||
<version>02.01.15-dev</version>
|
||||
<version>02.01.20-dev</version>
|
||||
<client>site</client>
|
||||
<folder>system</folder>
|
||||
<tags>
|
||||
@@ -19,10 +19,9 @@
|
||||
</tags>
|
||||
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/mokowaas-02.01.15-dev.zip</downloadurl>
|
||||
<downloadurl type="full" format="tar.gz">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/mokowaas-02.01.15-dev.tar.gz</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/mokowaas-02.01.20-dev.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>7fcd567f42dcdfee58aeb6fc82f904e1cd970be6ba2fae3690d279d7e48737ed</sha256>
|
||||
<sha256>edb7ccb285d9d5889a559c55b85e2555006c0b41040ddf0f8a4dd34f1ca0f14b</sha256>
|
||||
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
|
||||
Reference in New Issue
Block a user