Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a60a1ef00e |
+13
-13
@@ -1,4 +1,4 @@
|
||||
# MokoJoomStoreLocator
|
||||
# MokoSuiteStoreLocator
|
||||
|
||||
Store locator listing component with coordinating map and search modules for Joomla.
|
||||
|
||||
@@ -6,18 +6,18 @@ Store locator listing component with coordinating map and search modules for Joo
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Package** | `pkg_mokojoomstorelocator` |
|
||||
| **Package** | `pkg_mokosuitestorelocator` |
|
||||
| **Language** | PHP 8.1+ |
|
||||
| **Branch** | develop on `dev`, merge to `main` (protected) |
|
||||
| **Wiki** | [MokoJoomStoreLocator Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoJoomStoreLocator/wiki) |
|
||||
| **Wiki** | [MokoSuiteStoreLocator Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteStoreLocator/wiki) |
|
||||
|
||||
## Package Contents
|
||||
|
||||
| Extension | Type | Element |
|
||||
|---|---|---|
|
||||
| Store Locator Component | component | `com_mokojoomstorelocator` |
|
||||
| Store Locator Map | module (site) | `mod_mokojoomstorelocator_map` |
|
||||
| Store Locator Search | module (site) | `mod_mokojoomstorelocator_search` |
|
||||
| Store Locator Component | component | `com_mokosuitestorelocator` |
|
||||
| Store Locator Map | module (site) | `mod_mokosuitestorelocator_map` |
|
||||
| Store Locator Search | module (site) | `mod_mokosuitestorelocator_search` |
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -34,18 +34,18 @@ composer install # Install PHP dev dependencies
|
||||
|
||||
Joomla **package** with component + 2 modules:
|
||||
|
||||
- `src/pkg_mokojoomstorelocator.xml` — package manifest
|
||||
- `src/pkg_mokosuitestorelocator.xml` — package manifest
|
||||
- `src/script.php` — package install/upgrade/uninstall script
|
||||
- `src/packages/com_mokojoomstorelocator/` — main component
|
||||
- `src/packages/com_mokosuitestorelocator/` — main component
|
||||
- `admin/` — admin MVC (controllers, models, views, forms, tables, SQL)
|
||||
- `site/` — frontend MVC (controllers, models, views, templates)
|
||||
- `src/packages/mod_mokojoomstorelocator_map/` — map display module
|
||||
- `src/packages/mod_mokojoomstorelocator_search/` — search/filter module
|
||||
- `src/packages/mod_mokosuitestorelocator_map/` — map display module
|
||||
- `src/packages/mod_mokosuitestorelocator_search/` — search/filter module
|
||||
### Database Table
|
||||
|
||||
`#__mokojoomstorelocator_locations` — location data (coordinates, address, contact, business hours)
|
||||
`#__mokosuitestorelocator_locations` — location data (coordinates, address, contact, business hours)
|
||||
|
||||
Namespace: `Moko\Component\MokoJoomStoreLocator`
|
||||
Namespace: `Moko\Component\MokoSuiteStoreLocator`
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -53,7 +53,7 @@ Namespace: `Moko\Component\MokoJoomStoreLocator`
|
||||
- **Attribution**: `Authored-by: Moko Consulting`
|
||||
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
|
||||
- **Wiki**: documentation lives in the Gitea wiki, not `docs/` files
|
||||
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)
|
||||
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)
|
||||
|
||||
## Coding Standards
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ contact_links:
|
||||
url: https://mokoconsulting.tech/
|
||||
about: Get help or ask questions through our website
|
||||
- name: 📚 MokoStandards Documentation
|
||||
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
url: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
about: View our coding standards and best practices
|
||||
- name: 🔒 Report a Security Vulnerability
|
||||
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
|
||||
|
||||
@@ -1,324 +1,324 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||
# PATH: /templates/workflows/universal/auto-release.yml.template
|
||||
# VERSION: 05.00.00
|
||||
# BRIEF: Universal build & release � detects platform from manifest.xml
|
||||
#
|
||||
# +========================================================================+
|
||||
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
||||
# +========================================================================+
|
||||
# | |
|
||||
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
|
||||
# | |
|
||||
# | Platform-specific: |
|
||||
# | joomla: XML manifest, type-prefixed packages |
|
||||
# | dolibarr: mod*.class.php, update.txt, dev version reset |
|
||||
# | generic: README-only, no update stream |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
|
||||
name: "Universal: Build & Release"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, closed]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
action:
|
||||
description: 'Action to perform'
|
||||
required: false
|
||||
type: choice
|
||||
default: release
|
||||
options:
|
||||
- release
|
||||
- promote-rc
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
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 }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
|
||||
promote-rc:
|
||||
name: Promote to RC
|
||||
runs-on: release
|
||||
if: >-
|
||||
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup moko-platform tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/moko-platform
|
||||
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/moko-platform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
|
||||
cd /tmp/moko-platform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Rename branch to rc
|
||||
run: |
|
||||
php ${MOKO_CLI}/branch_rename.php \
|
||||
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||
--pr "${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Checkout rc and configure git
|
||||
run: |
|
||||
git fetch origin rc
|
||||
git checkout rc
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Publish RC release
|
||||
run: |
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
||||
release:
|
||||
name: Build & Release Pipeline
|
||||
runs-on: release
|
||||
if: >-
|
||||
github.event.pull_request.merged == true ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git for bot pushes
|
||||
run: |
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Check for merge conflict markers
|
||||
run: |
|
||||
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
|
||||
if [ -n "$CONFLICTS" ]; then
|
||||
echo "::error::Merge conflict markers found — aborting release"
|
||||
echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
echo "No conflict markers found"
|
||||
|
||||
- name: Setup moko-platform tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
run: |
|
||||
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/moko-platform
|
||||
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/moko-platform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
|
||||
cd /tmp/moko-platform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: "Publish stable release"
|
||||
run: |
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability stable --bump minor --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Update release notes from CHANGELOG.md
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
||||
[ -z "$NOTES" ] && NOTES="Stable release"
|
||||
else
|
||||
NOTES="Stable release"
|
||||
fi
|
||||
|
||||
# Update release body via API
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
python3 -c "
|
||||
import json, urllib.request
|
||||
body = open('/dev/stdin').read()
|
||||
payload = json.dumps({'body': body}).encode()
|
||||
req = urllib.request.Request(
|
||||
'${API_BASE}/releases/${RELEASE_ID}',
|
||||
data=payload, method='PATCH',
|
||||
headers={
|
||||
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
urllib.request.urlopen(req)
|
||||
" <<< "$NOTES"
|
||||
echo "Release notes updated from CHANGELOG.md"
|
||||
fi
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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="${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" \
|
||||
--gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
|
||||
--branch main 2>&1 || true
|
||||
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
|
||||
- name: "Step 10: Push main to GitHub mirror"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
continue-on-error: true
|
||||
run: |
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
|
||||
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
|
||||
git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
|
||||
git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
|
||||
git fetch origin main --depth=1
|
||||
git push github origin/main:refs/heads/main --force 2>/dev/null \
|
||||
&& echo "main branch pushed to GitHub mirror" \
|
||||
|| echo "WARNING: GitHub mirror push failed"
|
||||
|
||||
- name: "Step 11: Delete rc branch and recreate dev from main"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Delete rc branch (ephemeral — created by promote-rc)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/rc" 2>/dev/null \
|
||||
&& echo "Deleted rc branch" || echo "rc branch not found"
|
||||
|
||||
# Delete dev branch
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
|
||||
|
||||
# Recreate dev from main (now includes version bump + changelog promotion)
|
||||
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/branches" \
|
||||
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
|
||||
|
||||
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: "Step 12: Create version branch from main"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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}"
|
||||
MAIN_SHA=$(git rev-parse HEAD)
|
||||
|
||||
# Delete old version branch if it exists (same version re-release)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
|
||||
|
||||
# Create version/XX.YY.ZZ from main
|
||||
curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
|
||||
|
||||
echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
|
||||
|
||||
# -- Dolibarr post-release: Reset dev version -----------------------------
|
||||
- name: "Post-release: Reset dev version"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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
|
||||
|
||||
# -- Summary --------------------------------------------------------------
|
||||
- name: Pipeline Summary
|
||||
if: always()
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
|
||||
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
|
||||
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
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](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: mokoplatform.Release
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform
|
||||
# PATH: /templates/workflows/universal/auto-release.yml.template
|
||||
# VERSION: 05.00.00
|
||||
# BRIEF: Universal build & release � detects platform from manifest.xml
|
||||
#
|
||||
# +========================================================================+
|
||||
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
||||
# +========================================================================+
|
||||
# | |
|
||||
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
|
||||
# | |
|
||||
# | Platform-specific: |
|
||||
# | joomla: XML manifest, type-prefixed packages |
|
||||
# | dolibarr: mod*.class.php, update.txt, dev version reset |
|
||||
# | generic: README-only, no update stream |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
|
||||
name: "Universal: Build & Release"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, closed]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
action:
|
||||
description: 'Action to perform'
|
||||
required: false
|
||||
type: choice
|
||||
default: release
|
||||
options:
|
||||
- release
|
||||
- promote-rc
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
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 }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
|
||||
promote-rc:
|
||||
name: Promote to RC
|
||||
runs-on: release
|
||||
if: >-
|
||||
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup mokoplatform tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
run: |
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Rename branch to rc
|
||||
run: |
|
||||
php ${MOKO_CLI}/branch_rename.php \
|
||||
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||
--pr "${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Checkout rc and configure git
|
||||
run: |
|
||||
git fetch origin rc
|
||||
git checkout rc
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Publish RC release
|
||||
run: |
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
||||
release:
|
||||
name: Build & Release Pipeline
|
||||
runs-on: release
|
||||
if: >-
|
||||
github.event.pull_request.merged == true ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git for bot pushes
|
||||
run: |
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
- name: Check for merge conflict markers
|
||||
run: |
|
||||
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
|
||||
if [ -n "$CONFLICTS" ]; then
|
||||
echo "::error::Merge conflict markers found — aborting release"
|
||||
echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
echo "No conflict markers found"
|
||||
|
||||
- name: Setup mokoplatform tools
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
run: |
|
||||
if [ -f /opt/mokoplatform/cli/version_bump.php ] && [ -f /opt/mokoplatform/vendor/autoload.php ]; then
|
||||
echo Using pre-installed /opt/mokoplatform
|
||||
echo MOKO_CLI=/opt/mokoplatform/cli >> $GITHUB_ENV
|
||||
else
|
||||
echo Falling back to fresh clone
|
||||
if ! command -v composer > /dev/null 2>&1; then
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/mokoplatform-api
|
||||
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokoplatform.git
|
||||
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokoplatform-api
|
||||
cd /tmp/mokoplatform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
echo MOKO_CLI=/tmp/mokoplatform-api/cli >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: "Publish stable release"
|
||||
run: |
|
||||
php ${MOKO_CLI}/release_publish.php \
|
||||
--path . --stability stable --bump minor --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Update release notes from CHANGELOG.md
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# Extract [Unreleased] section from changelog
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
||||
[ -z "$NOTES" ] && NOTES="Stable release"
|
||||
else
|
||||
NOTES="Stable release"
|
||||
fi
|
||||
|
||||
# Update release body via API
|
||||
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -n "$RELEASE_ID" ]; then
|
||||
python3 -c "
|
||||
import json, urllib.request
|
||||
body = open('/dev/stdin').read()
|
||||
payload = json.dumps({'body': body}).encode()
|
||||
req = urllib.request.Request(
|
||||
'${API_BASE}/releases/${RELEASE_ID}',
|
||||
data=payload, method='PATCH',
|
||||
headers={
|
||||
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
urllib.request.urlopen(req)
|
||||
" <<< "$NOTES"
|
||||
echo "Release notes updated from CHANGELOG.md"
|
||||
fi
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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="${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" \
|
||||
--gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
|
||||
--branch main 2>&1 || true
|
||||
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
|
||||
- name: "Step 10: Push main to GitHub mirror"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
continue-on-error: true
|
||||
run: |
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
|
||||
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
|
||||
git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
|
||||
git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
|
||||
git fetch origin main --depth=1
|
||||
git push github origin/main:refs/heads/main --force 2>/dev/null \
|
||||
&& echo "main branch pushed to GitHub mirror" \
|
||||
|| echo "WARNING: GitHub mirror push failed"
|
||||
|
||||
- name: "Step 11: Delete rc branch and recreate dev from main"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# Delete rc branch (ephemeral — created by promote-rc)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/rc" 2>/dev/null \
|
||||
&& echo "Deleted rc branch" || echo "rc branch not found"
|
||||
|
||||
# Delete dev branch
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
|
||||
|
||||
# Recreate dev from main (now includes version bump + changelog promotion)
|
||||
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API_BASE}/branches" \
|
||||
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
|
||||
|
||||
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: "Step 12: Create version branch from main"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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}"
|
||||
MAIN_SHA=$(git rev-parse HEAD)
|
||||
|
||||
# Delete old version branch if it exists (same version re-release)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
|
||||
|
||||
# Create version/XX.YY.ZZ from main
|
||||
curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
|
||||
|
||||
echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
|
||||
|
||||
# -- Dolibarr post-release: Reset dev version -----------------------------
|
||||
- name: "Post-release: Reset dev version"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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
|
||||
|
||||
# -- Summary --------------------------------------------------------------
|
||||
- name: Pipeline Summary
|
||||
if: always()
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
|
||||
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
|
||||
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
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](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# INGROUP: mokoplatform.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.gitea/workflows/cleanup.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Security
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||
# INGROUP: mokoplatform.Security
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokoplatform
|
||||
# PATH: /templates/workflows/gitleaks.yml.template
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Notifications
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# INGROUP: mokoplatform.Notifications
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.gitea/workflows/notify.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Push notifications via ntfy on release success or workflow failure
|
||||
|
||||
+508
-508
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Security
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||
# INGROUP: mokoplatform.Security
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokoplatform
|
||||
# PATH: /.gitea/workflows/security-audit.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Dependency vulnerability scanning for composer and npm packages
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: {{DEFGROUP}}
|
||||
INGROUP: Project.Documentation
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoJoomTOS
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoSuiteTOS
|
||||
VERSION: 04.04.00
|
||||
PATH: ./CONTRIBUTING.md
|
||||
BRIEF: How to contribute; branch strategy, commit conventions, PR workflow, and release pipeline
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
# Contributing
|
||||
|
||||
Thank you for your interest in contributing to **MokoJoomTOS**!
|
||||
Thank you for your interest in contributing to **MokoSuiteTOS**!
|
||||
|
||||
This repository is governed by **[MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)** — the authoritative source of coding standards, workflows, and policies for all Moko Consulting repositories.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# ==============================================================================
|
||||
|
||||
# Extension Configuration
|
||||
EXTENSION_NAME := mokojoomstorelocator
|
||||
EXTENSION_NAME := mokosuitestorelocator
|
||||
EXTENSION_TYPE := package
|
||||
# Options: module, plugin, component, package, template
|
||||
EXTENSION_VERSION := 1.0.0
|
||||
@@ -114,7 +114,7 @@ build: clean validate ## Build package ZIP containing all sub-extensions
|
||||
cd $(BUILD_DIR) && $(ZIP) -r "pkg_$(EXTENSION_NAME)/$$EXT_NAME.zip" "$$EXT_NAME" && cd ..; \
|
||||
done
|
||||
@# Copy the package manifest
|
||||
@cp src/pkg_mokojoomstorelocator.xml $(BUILD_DIR)/pkg_$(EXTENSION_NAME)/
|
||||
@cp src/pkg_mokosuitestorelocator.xml $(BUILD_DIR)/pkg_$(EXTENSION_NAME)/
|
||||
@if [ -f "src/script.php" ]; then cp src/script.php $(BUILD_DIR)/pkg_$(EXTENSION_NAME)/; fi
|
||||
@# Create the final package ZIP
|
||||
@cd $(BUILD_DIR) && $(ZIP) -r "../$(DIST_DIR)/pkg_$(EXTENSION_NAME)-$(EXTENSION_VERSION).zip" "pkg_$(EXTENSION_NAME)"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# MokoJoomStoreLocator
|
||||
# MokoSuiteStoreLocator
|
||||
|
||||
A Joomla 4/5 package providing a store locator listing component with coordinating map and search modules.
|
||||
|
||||
@@ -6,9 +6,9 @@ A Joomla 4/5 package providing a store locator listing component with coordinati
|
||||
|
||||
| Extension | Description |
|
||||
|---|---|
|
||||
| `com_mokojoomstorelocator` | Component for managing store locations (admin CRUD + frontend listing) |
|
||||
| `mod_mokojoomstorelocator_map` | Site module displaying an interactive map with location markers |
|
||||
| `mod_mokojoomstorelocator_search` | Site module providing search/filter form for finding locations |
|
||||
| `com_mokosuitestorelocator` | Component for managing store locations (admin CRUD + frontend listing) |
|
||||
| `mod_mokosuitestorelocator_map` | Site module displaying an interactive map with location markers |
|
||||
| `mod_mokosuitestorelocator_search` | Site module providing search/filter form for finding locations |
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -18,7 +18,7 @@ A Joomla 4/5 package providing a store locator listing component with coordinati
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the latest `pkg_mokojoomstorelocator-x.x.x.zip` from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoJoomStoreLocator/releases)
|
||||
1. Download the latest `pkg_mokosuitestorelocator-x.x.x.zip` from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteStoreLocator/releases)
|
||||
2. In Joomla Administrator, go to **System > Install > Extensions**
|
||||
3. Upload the package ZIP — all extensions install automatically
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "mokoconsulting/mokojoomstorelocator",
|
||||
"name": "mokoconsulting/mokosuitestorelocator",
|
||||
"description": "Joomla store locator listing package with component and modules",
|
||||
"type": "joomla-package",
|
||||
"license": "GPL-3.0-or-later",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage pkg_mokojoomstorelocator
|
||||
* @package MokoSuiteStoreLocator
|
||||
* @subpackage pkg_mokosuitestorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
@@ -24,14 +24,14 @@ class Pkg_MokojoomstorelocatorInstallerScript
|
||||
{
|
||||
if (version_compare(PHP_VERSION, $this->minimumPhp, '<'))
|
||||
{
|
||||
Log::add('MokoJoomStoreLocator requires PHP ' . $this->minimumPhp . ' or later.', Log::WARNING, 'jerror');
|
||||
Log::add('MokoSuiteStoreLocator requires PHP ' . $this->minimumPhp . ' or later.', Log::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version_compare(JVERSION, $this->minimumJoomla, '<'))
|
||||
{
|
||||
Log::add('MokoJoomStoreLocator requires Joomla ' . $this->minimumJoomla . ' or later.', Log::WARNING, 'jerror');
|
||||
Log::add('MokoSuiteStoreLocator requires Joomla ' . $this->minimumJoomla . ' or later.', Log::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class Pkg_MokojoomstorelocatorInstallerScript
|
||||
->from($db->quoteName('#__update_sites', 'us'))
|
||||
->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id')
|
||||
->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id')
|
||||
->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokojoomstorelocator'))
|
||||
->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokosuitestorelocator'))
|
||||
->setLimit(1)
|
||||
);
|
||||
$key = $db->loadResult();
|
||||
@@ -90,7 +90,7 @@ class Pkg_MokojoomstorelocatorInstallerScript
|
||||
->from($db->quoteName('#__update_sites', 'us'))
|
||||
->join('INNER', $db->quoteName('#__update_sites_extensions', 'use') . ' ON use.update_site_id = us.update_site_id')
|
||||
->join('INNER', $db->quoteName('#__extensions', 'e') . ' ON e.extension_id = use.extension_id')
|
||||
->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokojoomstorelocator'))
|
||||
->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_mokosuitestorelocator'))
|
||||
->setLimit(1)
|
||||
);
|
||||
$siteId = (int) $db->loadResult();
|
||||
@@ -116,7 +116,7 @@ class Pkg_MokojoomstorelocatorInstallerScript
|
||||
$db->getQuery(true)
|
||||
->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query')])
|
||||
->from($db->quoteName('#__update_sites'))
|
||||
->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoJoomStoreLocator%') . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoJoomStoreLocator%') . ')')
|
||||
->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoSuiteStoreLocator%') . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoSuiteStoreLocator%') . ')')
|
||||
->setLimit(1)
|
||||
);
|
||||
$site = $db->loadObject();
|
||||
@@ -1,140 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Location edit form -->
|
||||
<form>
|
||||
<fieldset name="details" addfieldprefix="Moko\Component\MokoJoomStoreLocator\Administrator\Field">
|
||||
<field
|
||||
name="id"
|
||||
type="hidden"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="JGLOBAL_TITLE"
|
||||
required="true"
|
||||
size="40"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="alias"
|
||||
type="text"
|
||||
label="JFIELD_ALIAS_LABEL"
|
||||
size="40"
|
||||
hint="JFIELD_ALIAS_PLACEHOLDER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="description"
|
||||
type="editor"
|
||||
label="JGLOBAL_DESCRIPTION"
|
||||
filter="safehtml"
|
||||
buttons="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="published"
|
||||
type="list"
|
||||
label="JSTATUS"
|
||||
default="1"
|
||||
>
|
||||
<option value="1">JPUBLISHED</option>
|
||||
<option value="0">JUNPUBLISHED</option>
|
||||
<option value="-2">JTRASHED</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="address" label="COM_MOKOJOOMSTORELOCATOR_FIELDSET_ADDRESS">
|
||||
<field
|
||||
name="address"
|
||||
type="text"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_ADDRESS"
|
||||
size="60"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="city"
|
||||
type="text"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_CITY"
|
||||
size="40"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="state"
|
||||
type="text"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_STATE"
|
||||
size="40"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="postcode"
|
||||
type="text"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_POSTCODE"
|
||||
size="20"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="country"
|
||||
type="text"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_COUNTRY"
|
||||
size="40"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="coordinates" label="COM_MOKOJOOMSTORELOCATOR_FIELDSET_COORDINATES">
|
||||
<field
|
||||
name="latitude"
|
||||
type="number"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_LATITUDE"
|
||||
step="0.00000001"
|
||||
min="-90"
|
||||
max="90"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="longitude"
|
||||
type="number"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_LONGITUDE"
|
||||
step="0.00000001"
|
||||
min="-180"
|
||||
max="180"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="contact" label="COM_MOKOJOOMSTORELOCATOR_FIELDSET_CONTACT">
|
||||
<field
|
||||
name="phone"
|
||||
type="tel"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_PHONE"
|
||||
size="30"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="email"
|
||||
type="email"
|
||||
label="JGLOBAL_EMAIL"
|
||||
size="40"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="website"
|
||||
type="url"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_WEBSITE"
|
||||
size="60"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="hours"
|
||||
type="textarea"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_HOURS"
|
||||
rows="5"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="image" label="COM_MOKOJOOMSTORELOCATOR_FIELDSET_IMAGE">
|
||||
<field
|
||||
name="image"
|
||||
type="media"
|
||||
label="COM_MOKOJOOMSTORELOCATOR_FIELD_IMAGE"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
; MokoJoomStoreLocator - Admin language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
COM_MOKOJOOMSTORELOCATOR="Store Locator"
|
||||
COM_MOKOJOOMSTORELOCATOR_DESC="A store locator component for managing and displaying location listings."
|
||||
COM_MOKOJOOMSTORELOCATOR_LOCATIONS="Locations"
|
||||
COM_MOKOJOOMSTORELOCATOR_LOCATION_NEW="New Location"
|
||||
COM_MOKOJOOMSTORELOCATOR_LOCATION_EDIT="Edit Location"
|
||||
COM_MOKOJOOMSTORELOCATOR_TABLE_CAPTION="Store Location List"
|
||||
|
||||
COM_MOKOJOOMSTORELOCATOR_CITY="City"
|
||||
COM_MOKOJOOMSTORELOCATOR_STATE="State"
|
||||
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELDSET_ADDRESS="Address"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELDSET_COORDINATES="Coordinates"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELDSET_CONTACT="Contact Information"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELDSET_IMAGE="Image"
|
||||
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_ADDRESS="Street Address"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_CITY="City"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_STATE="State / Province"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_POSTCODE="Postal Code"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_COUNTRY="Country"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_LATITUDE="Latitude"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_LONGITUDE="Longitude"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_PHONE="Phone"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_WEBSITE="Website"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_HOURS="Business Hours"
|
||||
COM_MOKOJOOMSTORELOCATOR_FIELD_IMAGE="Location Image"
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
; MokoJoomStoreLocator - System language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
COM_MOKOJOOMSTORELOCATOR="Store Locator"
|
||||
COM_MOKOJOOMSTORELOCATOR_DESC="A store locator component for managing and displaying location listings."
|
||||
COM_MOKOJOOMSTORELOCATOR_LOCATIONS="Locations"
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Moko\Component\MokoJoomStoreLocator\Administrator\Extension\MokoJoomStoreLocatorComponent;
|
||||
|
||||
/**
|
||||
* The store locator service provider.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
return new class implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->registerServiceProvider(new MVCFactory('\\Moko\\Component\\MokoJoomStoreLocator'));
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Moko\\Component\\MokoJoomStoreLocator'));
|
||||
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
function (Container $container) {
|
||||
$component = new MokoJoomStoreLocatorComponent(
|
||||
$container->get(ComponentDispatcherFactoryInterface::class)
|
||||
);
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
-- =========================================================================
|
||||
-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
--
|
||||
-- MokoJoomStoreLocator - Store locations table
|
||||
-- =========================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__mokojoomstorelocator_locations` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`alias` varchar(400) NOT NULL DEFAULT '',
|
||||
`description` text NOT NULL,
|
||||
`address` varchar(255) NOT NULL DEFAULT '',
|
||||
`city` varchar(100) NOT NULL DEFAULT '',
|
||||
`state` varchar(100) NOT NULL DEFAULT '',
|
||||
`postcode` varchar(20) NOT NULL DEFAULT '',
|
||||
`country` varchar(100) NOT NULL DEFAULT '',
|
||||
`latitude` decimal(10, 8) DEFAULT NULL,
|
||||
`longitude` decimal(11, 8) DEFAULT NULL,
|
||||
`phone` varchar(50) NOT NULL DEFAULT '',
|
||||
`email` varchar(255) NOT NULL DEFAULT '',
|
||||
`website` varchar(255) NOT NULL DEFAULT '',
|
||||
`hours` text NOT NULL,
|
||||
`image` varchar(255) NOT NULL DEFAULT '',
|
||||
`published` tinyint(4) NOT NULL DEFAULT 0,
|
||||
`ordering` int(11) NOT NULL DEFAULT 0,
|
||||
`catid` int(11) NOT NULL DEFAULT 0,
|
||||
`params` text NOT NULL,
|
||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`created_by` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`modified_by` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`checked_out` int(10) unsigned DEFAULT NULL,
|
||||
`checked_out_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_published` (`published`),
|
||||
KEY `idx_catid` (`catid`),
|
||||
KEY `idx_alias` (`alias`(191)),
|
||||
KEY `idx_coordinates` (`latitude`, `longitude`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- =========================================================================
|
||||
-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-- =========================================================================
|
||||
|
||||
DROP TABLE IF EXISTS `#__mokojoomstorelocator_locations`;
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\Controller;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
|
||||
/**
|
||||
* Default controller for the admin side of the component.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The default view.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $default_view = 'locations';
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\Extension;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
|
||||
/**
|
||||
* Component class for com_mokojoomstorelocator.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class MokoJoomStoreLocatorComponent extends MVCComponent
|
||||
{
|
||||
// TODO: Add boot(), getRouterRules(), or custom services as needed
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Table\Table;
|
||||
|
||||
/**
|
||||
* Single location edit model.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class LocationModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* The type alias for this content type.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public $typeAlias = 'com_mokojoomstorelocator.location';
|
||||
|
||||
/**
|
||||
* Get the form for this model.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data.
|
||||
*
|
||||
* @return Form|boolean A Form object on success, false on failure.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
$form = $this->loadForm(
|
||||
'com_mokojoomstorelocator.location',
|
||||
'location',
|
||||
['control' => 'jform', 'load_data' => $loadData]
|
||||
);
|
||||
|
||||
if (empty($form))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the data for the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
$data = $this->getItem();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table for this model.
|
||||
*
|
||||
* @param string $name The table name.
|
||||
* @param string $prefix The table prefix.
|
||||
* @param array $options Configuration array for the table.
|
||||
*
|
||||
* @return Table
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getTable($name = 'Location', $prefix = 'Administrator', $options = [])
|
||||
{
|
||||
return parent::getTable($name, $prefix, $options);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\Model;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
/**
|
||||
* Locations list model for the admin view.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class LocationsModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if (empty($config['filter_fields']))
|
||||
{
|
||||
$config['filter_fields'] = [
|
||||
'id', 'a.id',
|
||||
'title', 'a.title',
|
||||
'city', 'a.city',
|
||||
'state', 'a.state',
|
||||
'published', 'a.published',
|
||||
'ordering', 'a.ordering',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return QueryInterface
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function getListQuery(): QueryInterface
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select('a.*')
|
||||
->from($db->quoteName('#__mokojoomstorelocator_locations', 'a'));
|
||||
|
||||
// TODO: Add filter by published state
|
||||
// TODO: Add filter by category
|
||||
// TODO: Add search filter
|
||||
// TODO: Add ordering clause
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\Table;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
|
||||
/**
|
||||
* Location table class.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class LocationTable extends Table
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DatabaseDriver $db Database driver object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db)
|
||||
{
|
||||
parent::__construct('#__mokojoomstorelocator_locations', 'id', $db);
|
||||
|
||||
$this->setColumnAlias('published', 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded check method to ensure data integrity.
|
||||
*
|
||||
* @return boolean True if the data is valid.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function check(): bool
|
||||
{
|
||||
// TODO: Validate title is not empty
|
||||
// TODO: Auto-generate alias from title if empty
|
||||
// TODO: Validate latitude/longitude ranges
|
||||
// TODO: Set created/modified timestamps
|
||||
|
||||
return parent::check();
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Component\MokoJoomStoreLocator\Administrator\View\Locations;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
/**
|
||||
* Locations list view for the admin.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The list of locations.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object.
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The model state.
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function addToolbar(): void
|
||||
{
|
||||
ToolbarHelper::title('Store Locator: Locations');
|
||||
ToolbarHelper::addNew('location.add');
|
||||
ToolbarHelper::publish('locations.publish', 'JTOOLBAR_PUBLISH', true);
|
||||
ToolbarHelper::unpublish('locations.unpublish', 'JTOOLBAR_UNPUBLISH', true);
|
||||
ToolbarHelper::deleteList('', 'locations.delete', 'JTOOLBAR_DELETE');
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage com_mokojoomstorelocator
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Moko\Component\MokoJoomStoreLocator\Administrator\View\Locations\HtmlView $this */
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_mokojoomstorelocator&view=locations'); ?>"
|
||||
method="post" name="adminForm" id="adminForm">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table" id="locationList">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_MOKOJOOMSTORELOCATOR_TABLE_CAPTION'); ?>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col">
|
||||
<?php echo Text::_('JGLOBAL_TITLE'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_MOKOJOOMSTORELOCATOR_CITY'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_MOKOJOOMSTORELOCATOR_STATE'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 text-center">
|
||||
<?php echo Text::_('JSTATUS'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 text-center">
|
||||
<?php echo Text::_('JGRID_HEADING_ID'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- TODO: Render location rows -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -1,62 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- =========================================================================
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
=========================================================================
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoJoomStoreLocator
|
||||
INGROUP: com_mokojoomstorelocator
|
||||
PATH: src/packages/com_mokojoomstorelocator/mokojoomstorelocator.xml
|
||||
VERSION: 01.00.00
|
||||
BRIEF: Component manifest for the store locator component
|
||||
=========================================================================
|
||||
-->
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_mokojoomstorelocator</name>
|
||||
<version>1.0.0</version>
|
||||
<creationDate>2026-05-21</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||
<description>COM_MOKOJOOMSTORELOCATOR_DESC</description>
|
||||
|
||||
<namespace path="src">Moko\Component\MokoJoomStoreLocator</namespace>
|
||||
|
||||
<install>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8">sql/install.mysql.sql</file>
|
||||
</sql>
|
||||
</install>
|
||||
|
||||
<uninstall>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8">sql/uninstall.mysql.sql</file>
|
||||
</sql>
|
||||
</uninstall>
|
||||
|
||||
<files folder="site">
|
||||
<folder>language</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<folder>forms</folder>
|
||||
<folder>language</folder>
|
||||
<folder>services</folder>
|
||||
<folder>sql</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
|
||||
<menu>COM_MOKOJOOMSTORELOCATOR</menu>
|
||||
<submenu>
|
||||
<menu link="option=com_mokojoomstorelocator&view=locations">COM_MOKOJOOMSTORELOCATOR_LOCATIONS</menu>
|
||||
</submenu>
|
||||
</administration>
|
||||
</extension>
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
; MokoJoomStoreLocator Map Module - Language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP="Store Locator Map"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_DESC="Displays an interactive map with store location markers."
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_HEIGHT="Map Height"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_ZOOM="Default Zoom Level"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_PROVIDER="Map Provider"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_API_KEY="API Key"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_API_KEY_DESC="Required for Google Maps. Not needed for OpenStreetMap."
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_NOSCRIPT="JavaScript is required to display the map."
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
; MokoJoomStoreLocator Map Module - System language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP="Store Locator Map"
|
||||
MOD_MOKOJOOMSTORELOCATOR_MAP_DESC="Displays an interactive map with store location markers."
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- =========================================================================
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
=========================================================================
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoJoomStoreLocator
|
||||
INGROUP: mod_mokojoomstorelocator_map
|
||||
PATH: src/packages/mod_mokojoomstorelocator_map/mod_mokojoomstorelocator_map.xml
|
||||
VERSION: 01.00.00
|
||||
BRIEF: Module manifest for the store locator map module
|
||||
=========================================================================
|
||||
-->
|
||||
<extension type="module" client="site" method="upgrade">
|
||||
<name>mod_mokojoomstorelocator_map</name>
|
||||
<version>1.0.0</version>
|
||||
<creationDate>2026-05-21</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||
<description>MOD_MOKOJOOMSTORELOCATOR_MAP_DESC</description>
|
||||
|
||||
<namespace path="src">Moko\Module\MokoJoomStoreLocatorMap</namespace>
|
||||
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic">
|
||||
<field
|
||||
name="map_height"
|
||||
type="text"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_MAP_HEIGHT"
|
||||
default="400px"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="map_zoom"
|
||||
type="number"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_MAP_ZOOM"
|
||||
default="10"
|
||||
min="1"
|
||||
max="20"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="map_provider"
|
||||
type="list"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_MAP_PROVIDER"
|
||||
default="leaflet"
|
||||
>
|
||||
<option value="leaflet">OpenStreetMap (Leaflet)</option>
|
||||
<option value="google">Google Maps</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="api_key"
|
||||
type="text"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_MAP_API_KEY"
|
||||
description="MOD_MOKOJOOMSTORELOCATOR_MAP_API_KEY_DESC"
|
||||
/>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage mod_mokojoomstorelocator_map
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Module\MokoJoomStoreLocatorMap\Dispatcher;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
|
||||
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
|
||||
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Dispatcher for mod_mokojoomstorelocator_map.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
|
||||
{
|
||||
use HelperFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Returns the layout data.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function getLayoutData(): array
|
||||
{
|
||||
$data = parent::getLayoutData();
|
||||
|
||||
// TODO: Load published locations with coordinates from the component table
|
||||
// TODO: Build marker data array for the map JS
|
||||
$data['locations'] = [];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage mod_mokojoomstorelocator_map
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
/** @var array $displayData */
|
||||
$params = $displayData['params'];
|
||||
$locations = $displayData['locations'] ?? [];
|
||||
$mapHeight = $params->get('map_height', '400px');
|
||||
$mapZoom = (int) $params->get('map_zoom', 10);
|
||||
$provider = $params->get('map_provider', 'leaflet');
|
||||
?>
|
||||
<div class="mod-mokojoomstorelocator-map"
|
||||
id="mokojoomstorelocator-map-<?php echo $displayData['module']->id; ?>"
|
||||
style="height: <?php echo $this->escape($mapHeight); ?>;"
|
||||
data-locations="<?php echo $this->escape(json_encode($locations)); ?>"
|
||||
data-zoom="<?php echo $mapZoom; ?>"
|
||||
data-provider="<?php echo $this->escape($provider); ?>">
|
||||
<!-- TODO: Map renders here via JavaScript -->
|
||||
<noscript>
|
||||
<p><?php echo Text::_('MOD_MOKOJOOMSTORELOCATOR_MAP_NOSCRIPT'); ?></p>
|
||||
</noscript>
|
||||
</div>
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
; MokoJoomStoreLocator Search Module - Language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH="Store Locator Search"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_DESC="Provides a search/filter form for finding store locations."
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_LABEL="Find a Store"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_PLACEHOLDER="Enter city, postcode, or address..."
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_SHOW_CITY="Show City Filter"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_SHOW_RADIUS="Show Radius Filter"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_UNIT="Distance Unit"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_OPTIONS="Radius Options"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_OPTIONS_DESC="Comma-separated list of radius values (e.g., 5,10,25,50,100)"
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
; MokoJoomStoreLocator Search Module - System language strings
|
||||
; Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
; License: GNU General Public License version 3 or later; see LICENSE
|
||||
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH="Store Locator Search"
|
||||
MOD_MOKOJOOMSTORELOCATOR_SEARCH_DESC="Provides a search/filter form for finding store locations."
|
||||
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- =========================================================================
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
=========================================================================
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoJoomStoreLocator
|
||||
INGROUP: mod_mokojoomstorelocator_search
|
||||
PATH: src/packages/mod_mokojoomstorelocator_search/mod_mokojoomstorelocator_search.xml
|
||||
VERSION: 01.00.00
|
||||
BRIEF: Module manifest for the store locator search module
|
||||
=========================================================================
|
||||
-->
|
||||
<extension type="module" client="site" method="upgrade">
|
||||
<name>mod_mokojoomstorelocator_search</name>
|
||||
<version>1.0.0</version>
|
||||
<creationDate>2026-05-21</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||
<description>MOD_MOKOJOOMSTORELOCATOR_SEARCH_DESC</description>
|
||||
|
||||
<namespace path="src">Moko\Module\MokoJoomStoreLocatorSearch</namespace>
|
||||
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic">
|
||||
<field
|
||||
name="show_city_filter"
|
||||
type="radio"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_SEARCH_SHOW_CITY"
|
||||
default="1"
|
||||
class="btn-group"
|
||||
>
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_radius_filter"
|
||||
type="radio"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_SEARCH_SHOW_RADIUS"
|
||||
default="1"
|
||||
class="btn-group"
|
||||
>
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="radius_unit"
|
||||
type="list"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_UNIT"
|
||||
default="miles"
|
||||
>
|
||||
<option value="miles">Miles</option>
|
||||
<option value="km">Kilometres</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="radius_options"
|
||||
type="text"
|
||||
label="MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_OPTIONS"
|
||||
default="5,10,25,50,100"
|
||||
description="MOD_MOKOJOOMSTORELOCATOR_SEARCH_RADIUS_OPTIONS_DESC"
|
||||
/>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage mod_mokojoomstorelocator_search
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Module\MokoJoomStoreLocatorSearch\Dispatcher;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
|
||||
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
|
||||
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Dispatcher for mod_mokojoomstorelocator_search.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
|
||||
{
|
||||
use HelperFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Returns the layout data.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function getLayoutData(): array
|
||||
{
|
||||
$data = parent::getLayoutData();
|
||||
|
||||
// TODO: Load distinct cities/states for filter dropdowns
|
||||
// TODO: Build radius options array from params
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoJoomStoreLocator
|
||||
* @subpackage mod_mokojoomstorelocator_search
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var array $displayData */
|
||||
$params = $displayData['params'];
|
||||
?>
|
||||
<div class="mod-mokojoomstorelocator-search">
|
||||
<form action="<?php echo Route::_('index.php?option=com_mokojoomstorelocator&view=locations'); ?>"
|
||||
method="get" class="mokojoomstorelocator-search-form">
|
||||
|
||||
<div class="mokojoomstorelocator-search-field">
|
||||
<label for="mokojoomstorelocator-query">
|
||||
<?php echo Text::_('MOD_MOKOJOOMSTORELOCATOR_SEARCH_LABEL'); ?>
|
||||
</label>
|
||||
<input type="text"
|
||||
id="mokojoomstorelocator-query"
|
||||
name="filter_search"
|
||||
placeholder="<?php echo Text::_('MOD_MOKOJOOMSTORELOCATOR_SEARCH_PLACEHOLDER'); ?>"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- TODO: City dropdown filter -->
|
||||
<!-- TODO: Radius dropdown filter -->
|
||||
<!-- TODO: Geolocation "Use my location" button -->
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo Text::_('JSEARCH_FILTER_SUBMIT'); ?>
|
||||
</button>
|
||||
|
||||
<input type="hidden" name="option" value="com_mokojoomstorelocator" />
|
||||
<input type="hidden" name="view" value="locations" />
|
||||
</form>
|
||||
</div>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- =========================================================================
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
=========================================================================
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoJoomStoreLocator
|
||||
INGROUP: pkg_mokojoomstorelocator
|
||||
PATH: src/pkg_mokojoomstorelocator.xml
|
||||
VERSION: 01.00.00
|
||||
BRIEF: Package manifest for the MokoJoomStoreLocator package
|
||||
=========================================================================
|
||||
-->
|
||||
<extension type="package" method="upgrade">
|
||||
<name>pkg_mokojoomstorelocator</name>
|
||||
<packagename>mokojoomstorelocator</packagename>
|
||||
<version>1.0.0</version>
|
||||
<creationDate>2026-05-21</creationDate>
|
||||
<author>Moko Consulting</author>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||
<description>PKG_MOKOJOOMSTORELOCATOR_DESC</description>
|
||||
<scriptfile>script.php</scriptfile>
|
||||
|
||||
<files>
|
||||
<file type="component" id="com_mokojoomstorelocator">com_mokojoomstorelocator.zip</file>
|
||||
<file type="module" id="mod_mokojoomstorelocator_map" client="site">mod_mokojoomstorelocator_map.zip</file>
|
||||
<file type="module" id="mod_mokojoomstorelocator_search" client="site">mod_mokojoomstorelocator_search.zip</file>
|
||||
</files>
|
||||
|
||||
<updateservers>
|
||||
<server type="extension" name="MokoJoomStoreLocator Updates">https://git.mokoconsulting.tech/MokoConsulting/MokoJoomStoreLocator/updates.xml</server>
|
||||
</updateservers>
|
||||
<dlid prefix="dlid=" suffix=""/>
|
||||
<blockChildUninstall>true</blockChildUninstall>
|
||||
</extension>
|
||||
Reference in New Issue
Block a user