Clone
Architecture
Package Structure
pkg_mokoog
com_mokoog -- Admin component (dashboard, tag CRUD, batch, CSV, ACL)
plg_system_mokoog -- System plugin (frontend meta tag injection, sitemap, AI)
plg_content_mokoog -- Content plugin (editor form fields, live preview)
plg_webservices_mokoog -- WebServices plugin (REST API routes)
Targets Joomla 6+ and PHP 8.2+. All extensions use the modern namespaced DI architecture: services/provider.php providers, SubscriberInterface event subscribers, and namespaced MVC. No deprecated Factory::getDbo/getUser/getSession/getLanguage, Joomla\CMS\Filesystem, or jexit() calls remain (forward-compatible with Joomla 7).
Data Flow
Frontend (onBeforeCompileHead)
- System plugin detects the current page (
option,view,id) - Loads custom OG data from
#__mokoog_tags(language-aware) - Falls back to category/menu OG data if available
- Auto-generates missing fields from article/product content
- Resolves the image URL, auto-resizes if enabled
- Emits OG, Twitter, LinkedIn, Discord, Telegram, Fediverse, Pinterest meta tags
- Builds JSON-LD schema(s) (Article/Product/WebPage + FAQ/HowTo/Event/Recipe/LocalBusiness/Video/custom)
- Fires
onMokoOGAfterRenderfor third-party extensions
Editor (content plugin)
- Content plugin adds the OG fields tab to article/menu/category editor forms
- On save, stores custom OG data to
#__mokoog_tagskeyed by language; JSON fields are validated as objects/arrays - Live preview updates the Facebook/Twitter/LinkedIn/Discord/Mastodon/Slack cards in real time
Admin component
- Dashboard (default view) —
DashboardModelcomputes coverage stats;View/Dashboardrenders a donut + breakdown + missing-articles list - Tags — list view with publish/unpublish/delete (
TagsController) and a single-record create/edit screen (TagController→View/Tag→tmpl/tag/edit.php) - Batch / Import-Export —
BatchController,ImportExportController(CSRF + ACL gated)
API
- WebServices plugin registers routes on
onBeforeApiRoute - JSON:API controller provides full CRUD plus a content-lookup endpoint
- A field whitelist (
JsonapiView) prevents information leakage
Key Classes
| Class | Location | Purpose |
|---|---|---|
| MokoOG | plg_system_mokoog | Meta tag injection, sitemap trigger, AI AJAX endpoint |
| MokoOGContent | plg_content_mokoog | Editor form injection, OG data save/load |
| MokoOGWebServices | plg_webservices_mokoog | API route registration |
| DisplayController | com_mokoog | Default view dispatch (→ dashboard) |
| DashboardModel | com_mokoog | Coverage metrics queries |
| TagController / TagsController | com_mokoog | Single-record edit / list operations |
| BatchController | com_mokoog | Batch OG generation |
| ImportExportController | com_mokoog | CSV import/export (JSON/URL validated) |
| TagTable | com_mokoog | DB table with field validation |
| ImageHelper | plg_system_mokoog | Image resize, center-crop, per-platform crops, prune |
| JsonLdBuilder | plg_system_mokoog | All JSON-LD schema builders + toScriptTag() |
| SitemapBuilder | plg_system_mokoog | Access-filtered XML sitemap, atomic write |
Database
Single table: #__mokoog_tags
- Unique key:
(content_type, content_id, language) - Supports:
com_content,com_content.category,menu,com_mokoshop - Columns include
og_*,seo_title,meta_description,robots,canonical_url,og_video,event_data,recipe_data,custom_schema,language,published - Language-aware queries prefer a specific language over the
*wildcard
Performance & Safety
loadArticle()/loadShopProduct()use static per-request caching (including negative lookups) — one query instead of several when the image finder, date extractor, and JSON-LD builder all need the same record- Batch processing is capped per request
- Generated images are cached under
images/mokoog/generated/and pruned after 30 days - The sitemap excludes non-public content and writes via a temp file + atomic rename
- Custom JSON-LD is validated as an object/array on save and guarded on render, so malformed data cannot crash the public page