Contents Reference Public

Module Research Notes

Evidence gathered from the current Contents module files — controllers, models, configs, and migrations — before writing these user guide pages.

Guide version: r1 Module version: 1.0.0 Updated: 2026-07-30 Estimated time: 5 min
You are viewing version r1 of this guide. View the current version
Module Research Notes

Contents

Evidence gathered from the current module files before writing the user guide pages.

Slug: contentVersion: 1.0.0Category: ContentsReviewed: 2026-07-11

Research Sources Inspected

Source path

modules/Content

Feature flags marked true

  • Controllers
  • Models
  • Views
  • Libraries
  • Language
  • Permissions
  • Left Menu
  • Default Menu
  • Routes
  • Migrations
  • Cron Jobs
  • Helpers
  • Api Endpoints
  • Components

Evidence Summary

Manifest

module.json defines slug content, version 1.0.0, category Contents, and the module capability flags used in this guide.

Runtime surface

7 controller file(s), 56 view file(s), and 22 route mapping(s) were found.

Data surface

25 model file(s), 28 declared table(s), and 2 migration file(s) were found.

Operations surface

27 permission key(s), 6 job(s), 3 seeder(s), and 20 test file(s) were found.

Detailed File Evidence

Controllers and methods

  • Content
  • Content_admin
  • Content_api - pages, page, posts, post, categories, tags, comments, media
  • Content_euapi - posts, post, page, comments, recommendations, postComment, addReaction, removeReaction
  • Content_feed
  • Content_preview
  • Content_sitemap

Jobs and schedules

  • Aggregate CMS analytics (daily) (15 0 * * *) - Rolls up yesterday
  • Expire lapsed CMS commenter bans (0 * * * *) - Lifts CMS commenter bans whose expiry has elapsed (system lift) and records the unban in the moderation log + audit trail. Permanent bans are left untouched.
  • Publish scheduled CMS content (*/5 * * * *) - Promotes scheduled CMS pages/posts to published once their scheduled time arrives, snapshots the published revision and records the audit event.
  • Regenerate CMS sitemap (0 4 * * *) - Rebuilds the public CMS XML sitemap (public/sitemap-cms.xml) from the current published, public, indexable pages/posts and active taxonomy archives.
  • Run queued CMS Lighthouse tests (*/10 * * * *) - Processes a small batch of queued CMS Lighthouse/PageSpeed runs via the PageSpeed Insights API (never blocks publishing). Skips when Lighthouse is disabled.
  • Scan held CMS comments (AkbAI moderation) (*/2 * * * *) - Runs AkbAI/local moderation on the verdict-less pending CMS comment backlog and persists each verdict. The async path so a visitor submission is never blocked by AkbAI downtime.

Routes sampled

RouteTarget
content_adminContent_admin/index
content_admin/(:any)/(:any)/(:any)Content_admin/$1/$2/$3
content_admin/(:any)/(:any)Content_admin/$1/$2
content_admin/(:any)Content_admin/$1
cms/preview/(:any)Content_preview/show/$1
sitemap-cms.xmlContent_sitemap/index
feed-cms.xmlContent_feed/rss
feed-cms.jsonContent_feed/json_feed
cms/content/(:num)/viewContent/track_view/$1
cms/content/(:num)/commentContent/comment/$1
cms/content/(:num)/reactionContent/react/$1
blogContent/blog_index
blog/(:any)Content/post/$1
category/(:any)Content/category/$1
tag/(:any)Content/tag/$1
author/(:any)Content/author/$1
page/(:any)Content/page/$1
content/page/(:any)Content/page/$1
content/post/(:any)Content/post/$1
contentContent/index
2 additional route(s) omitted for readability.

README topics

  • Key architecture facts
  • Make it visible
  • Layout
  • Demo seeders

Operating Implications

  • Permission coverage is part of the module contract, so every workflow should be tested with a role-limited user and an administrator.
  • The module has migrations, so fresh installs and tenant databases need migration validation before go-live.
  • The module has API documentation or routes, so response examples and query filters should stay aligned with user-facing screens.
  • Scheduled jobs can change statuses, notifications, or summaries after users leave the screen; support should check cron status during troubleshooting.
  • Seeders exist for sample or starter data; operators should know whether seeded records are demo-only or operational defaults.

Known Risks from the Manifest

  • All 23 cms_* tables are GLOBAL/public content pinned to the PRIMARY database by Cms_base_model (every Cms_*_model opens the 'default' connection). Module migrations still run per-tenant via migrate:modules, but up()/down() are a no-op on tenant connections (guarded by is_tenant_loaded()); any empty cms_* tables in a tenant DB are unused - the canonical store is the primary DB (plan section 18.5). There is no 'primary_db_only' manifest flag in ERPat; the base-model pin is the enforcement mechanism.
  • Public POST endpoints (comment, reaction, view) require the native CodeIgniter CSRF token, which the public layout renders for AJAX. The module-owned End-User API (/v1/api/cms/*) is stateless JWT bearer-authenticated, so CSRF must NOT be enforced on that surface (like the rest of the EU/integration API).
  • Route overrides (homepage /, module index /community) are OFF by default (cms.route_overrides_enabled / cms.homepage_override_enabled / cms.module_overrides_enabled = 0). The existing system homepage and Community controller index remain the live fallback until an authorized user (content_routes_activate) activates an assignment to a PUBLISHED CMS page; every activation/rollback is audit-logged and reversible.
  • AkbAI comment safety (scan + optional reply) is OFF by default (cms.akbai_comment_scan_enabled / cms.akbai_comment_reply_enabled = 0; cms.comment_moderation_mode = advisory). Comment text is treated strictly as untrusted DATA by a fixed classifier prompt (prompt-injection defense, section 8.23.1); AkbAI downtime never blocks submission (local heuristic fallback / queue as pending).
  • Guest comment emails are never persisted in plaintext - only an HMAC-SHA256 hash (visitor_email_hash) is stored; guest bans key on an HMAC visitor_hash, never a bare IP.
  • THEMES: public CMS pages render through the active theme (cms.active_theme, default 'default') via CmsThemeService::render_page(), which returns FALSE (emitting nothing) on any missing/disabled/erroring theme so the controller falls back to the legacy content/public/* view - the public site can never blank or 500 because of a theme. Theme templates are developer-authored CODE (like component view.php); the admin edits only theme OPTION DATA (cms_theme_settings), never template code. Theme switch records the previous theme for one-click revert and is audit-logged.
  • MENUS: the top-bar/footer navigation is backend-managed (cms_menus/cms_menu_items, primary-DB only). module_page items render only when module_enabled(module_key) is true and core_page items only when the target route exists - failing items are silently dropped from the public menu (never a broken link) and flagged in the admin builder. External custom_url items are forced rel=noopener noreferrer; internal targets are validated against reserved/admin paths.

Report a content problem