Building a CMS Adapter
A CMS adapter installs through the platform, keeps its settings in the platform’s own store, and adds a chat page and admin pages. This page compares how the six CMS adapters solve the same problems, so a new adapter can follow the closest one.
What they share
Section titled “What they share”- The same three tables:
phpclaw_conversations,phpclaw_messagesandphpclaw_memory, with the platform’s table prefix. PrestaShop adds a fourth,phpclaw_api_token, for its per-employee REST tokens. - The same settings: provider, model, API key, base URL, system prompt, store messages, max iterations (default 20), remote skill URLs, the three cloud fields, and the seven building block fields: fallback provider, model and key, rate limit, response cache and its TTL, and max token budget.
- A fixed memory driver. None of the six lets the site owner choose one.
- A permission for using the chat, a higher tier for seeing every user’s conversations, and an
owner column on
phpclaw_conversations. - Two commands: one to send a message and one to start the MCP server. No command reads or deletes stored conversations; Drupal’s chat page is the only screen that deletes one.
- Lifecycle events forwarded into the platform’s own event system, and a way for other extensions to add tools, guards, hooks, skills, memory drivers and providers.
Settings and memory
Section titled “Settings and memory”| Platform | Settings stored in | Memory driver |
|---|---|---|
| WordPress | the phpclaw_settings option | wpdb_router |
| Joomla | the phpClaw AI Agent system plugin’s parameters | joomladb |
| Drupal | the phpclaw.settings config object | database |
| Magento | core_config_data under phpclaw/ | router memory |
| PrestaShop | Configuration keys prefixed PHPCLAW_ | ps_router |
| OpenCart | OpenCart’s settings | oc_router |
Where the agent is built
Section titled “Where the agent is built”There is no shared adapter base class. Each CMS builds the agent in its own classes:
| Platform | Classes |
|---|---|
| WordPress | Plugin::getInstance() and the static Engine\EngineFactory::build() |
| Joomla | Engine\EngineFactory::build(), with EngineBootstrapper and ToolBuilder |
| Drupal | PhpClawRegistrar, and PhpClawServiceFactory::create() or createChat() for the two tool sets |
| Magento | Factory\PhpClawFactory::create() behind PhpClawFactoryInterface |
| PrestaShop | Plugin::getInstance() and Engine\EngineFactory::build() |
| OpenCart | Plugin::getInstance() and Engine\OcEngineFactory::build(); Factory\PhpClawFactory::create() for PhpClawLibrary |
Drupal’s admin pages are the controllers PhpClawAboutController, PhpClawAnalyticsController,
PhpClawChatController and PhpClawGuideController, plus the Settings form PhpClawSettingsForm.
PhpClawChatStreamController serves the Chat page’s POST stream endpoint.
No CMS adapter runs agent work in the background: there is no queue or scheduled job for agent runs.
Permissions and ownership
Section titled “Permissions and ownership”| Platform | Use the chat and tools | See every conversation | Owner column |
|---|---|---|---|
| WordPress | phpclaw_use_chat (derived from manage_options or edit_posts) | phpclaw_manage_all_conversations | user_id |
| Joomla | phpclaw.chat.use on com_phpclaw | phpclaw.chat.manageall | user_id |
| Drupal | use phpclaw chat | manage all phpclaw conversations | user_id |
| Magento | PhpClaw_Magento::phpclaw_chat | PhpClaw_Magento::phpclaw_settings | admin_user_id |
| PrestaShop | view on the Chat tab | the SuperAdmin profile | id_employee |
| OpenCart | access on the phpClaw route | access on the route’s /manage_all | owner_id |
Conversations created from the command line store 0 as the owner in every adapter. When you write a
check that spans adapters, take the owner column as a parameter.
In each adapter the chat permission reaches every platform tool, except raw SQL in PrestaShop
(SuperAdmin) and OpenCart (/manage_all). Treat it as administrator-level.
| Platform | Routes | Authentication |
|---|---|---|
| WordPress | /wp-json/phpclaw/send, /wp-json/phpclaw/chat/stream | WordPress REST authentication |
| Joomla | api/index.php/v1/phpclaw/chat, .../chat/stream | Joomla API token |
| Drupal | /api/phpclaw/send, /api/phpclaw/chat/stream | Drupal authentication providers |
| Magento | /rest/V1/phpclaw/send, /rest/V1/phpclaw/chat/stream | admin bearer token |
| PrestaShop | the module front controller, action=send or action=chat/stream | per-employee bearer token or back office session |
| OpenCart | none; the chat uses admin routes | admin session |
Admin-only actions stay off these routes. WordPress’s chat page and Test Connection use admin-ajax.php
(phpclaw_send, phpclaw_stream, phpclaw_test_connection). Joomla’s settings save, plugin enable
and Test Connection run through the component’s admin ApiController, behind core.admin.
Command line
Section titled “Command line”| Platform | Send a message | MCP server |
|---|---|---|
| WordPress | wp phpclaw send | wp phpclaw mcp-server |
| Joomla | php cli/joomla.php phpclaw | php cli/joomla.php phpclaw:mcp-server |
| Drupal | drush phpclaw:run | drush phpclaw:mcp-server |
| Magento | bin/magento phpclaw:run | bin/magento phpclaw:mcp-server |
| PrestaShop | php modules/phpclaw/cli/phpclaw.php send | ... mcp-server |
| OpenCart | php extension/phpclaw/cli/phpclaw.php send (OpenCart 4) or php system/library/phpclaw/cli/phpclaw.php send (OpenCart 3) | ... mcp-server |
An MCP server started from the command line must build file_write with PHP writes off and must not
skip the raw-SQL permission just because it runs in a terminal. See the cautions on the
PrestaShop and OpenCart pages.
Events and extension points
Section titled “Events and extension points”| Platform | Lifecycle events forwarded as | Extensions add through |
|---|---|---|
| WordPress | action phpclaw_{event} | filters phpclaw_extra_tools, _guards, _hooks, _skills, _memory_drivers, _providers |
| Joomla | event onPhpClaw{Event}, currently delivers nothing | plugin events onPhpClawExtraTools, ...Guards, ...Hooks, ...Skills, ...MemoryDrivers, ...Providers |
| Drupal | PhpClawEvent named phpclaw.{event} | service tags phpclaw.tool, phpclaw.guard, phpclaw.skill, phpclaw.provider, phpclaw.memory_driver, phpclaw.hook_listener |
| Magento | event phpclaw_{event} with dots as underscores | observers of phpclaw_extra_tools, _skills, _guards, _hooks, _memory, _providers |
| PrestaShop | hook actionPhpClaw{Event} | hooks actionPhpclawExtraTools, ...Guards, ...Hooks, ...Skills, ...Memory, ...Providers |
| OpenCart | event phpclaw/{event} | events phpclaw/extra/tools, .../guards, .../hooks, .../skills, .../memory, .../providers |
All forward the 54 events of PhpClaw\Hooks\LifecycleEvent, except Joomla, whose bridge delivers no
event. See Hooks and Joomla: lifecycle events.
WordPress checks for updates on WordPress’s own pre_set_site_transient_update_plugins filter and
caches the answer for 12 hours; OpenCart and PrestaShop show a notice from their own AutoUpdater.
On PrestaShop 9, Controller::ajaxDie() no longer exists, so admin JSON goes through
AdminPhpClawBaseController::respondJson(), which works on 8 and 9.
For each adapter’s full reference, see All Adapters.