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. - The same settings: provider, model, API key, base URL, system prompt, store messages, max iterations (default 20), remote skill URLs, and the three cloud fields.
- 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.
- 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 System - phpClaw 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, PhpClawChatStreamController and PhpClawGuideController.
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 cli/phpclaw.php send | ... 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 40 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.