docs: add known issues and working patterns
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
# Known Issues & Working Patterns
|
||||
|
||||
Critical bugs discovered, diagnosed, and fixed during development. Read before touching Elementor or page builds.
|
||||
|
||||
---
|
||||
|
||||
## 1. ElementorData WP Object Cache Bug (FIXED)
|
||||
|
||||
**File:** `includes/Elementor/Data/ElementorData.php`
|
||||
|
||||
**Problem:**
|
||||
In long-running PHP CLI scripts, WP object cache caused stale reads. After `wp_insert_post()`, WP caches `_elementor_data` as empty. Subsequent `update_post_meta()` calls write correctly to the DB but `get_post_meta()` within the same process returns the cached empty value. Each `elementor_add_container()` call then read the stale empty cache, added one element to an empty array, and overwrote the DB — only ever saving a single-element array instead of accumulating.
|
||||
|
||||
**Symptom:**
|
||||
Page shows 0 root sections after a full build. DB row for `_elementor_data` is `[]` or contains only the last element added.
|
||||
|
||||
**Fix:**
|
||||
Both `save_page_data()` and `get_page_data()` use raw `$wpdb` queries — bypassing WP object cache entirely — when `PHP_SAPI === 'cli'` OR `defined('DOING_CRON') && DOING_CRON`:
|
||||
|
||||
```php
|
||||
// save_page_data (CLI branch)
|
||||
$exists = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT meta_id FROM {$table} WHERE post_id=%d AND meta_key='_elementor_data' LIMIT 1",
|
||||
$post_id
|
||||
));
|
||||
if ($exists) {
|
||||
$wpdb->query($wpdb->prepare("UPDATE {$table} SET meta_value=%s WHERE meta_id=%d", $json, (int)$exists));
|
||||
} else {
|
||||
$wpdb->query($wpdb->prepare("INSERT INTO {$table} (post_id, meta_key, meta_value) VALUES (%d, '_elementor_data', %s)", $post_id, $json));
|
||||
}
|
||||
wp_cache_delete($post_id, 'post_meta');
|
||||
|
||||
// get_page_data (CLI branch)
|
||||
$raw = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id=%d AND meta_key='_elementor_data' LIMIT 1",
|
||||
$post_id
|
||||
));
|
||||
```
|
||||
|
||||
**Rule:**
|
||||
Always include `define('DOING_CRON', true)` at the top of any CLI script that builds Elementor pages.
|
||||
|
||||
---
|
||||
|
||||
## 2. Page Template Validation in CLI (FIXED)
|
||||
|
||||
**File:** `includes/Tools/PageTools.php`
|
||||
|
||||
**Problem:**
|
||||
Passing `page_template` to `wp_update_post()` in CLI context throws `WP_Error: Invalid page template`. WordPress validates the template slug against registered templates, which only exist during HTTP requests (themes register them on the `init` hook, which doesn't fully fire in CLI).
|
||||
|
||||
**Symptom:**
|
||||
```
|
||||
Publish error: Invalid page template.
|
||||
```
|
||||
Page status reverts or publish fails when template is set via `wp_update_post()`.
|
||||
|
||||
**Fix:**
|
||||
Never pass `page_template` to `wp_update_post()`. Set it via `update_post_meta()` after the `wp_update_post()` call:
|
||||
|
||||
```php
|
||||
// WRONG
|
||||
wp_update_post(['ID' => $pid, 'post_status' => 'publish', 'page_template' => 'elementor-full-width']);
|
||||
|
||||
// CORRECT
|
||||
wp_update_post(['ID' => $pid, 'post_status' => 'publish']);
|
||||
update_post_meta($pid, '_wp_page_template', 'elementor-full-width');
|
||||
```
|
||||
|
||||
`PageTools.php` has this fix applied. The template is set via meta in both `createPage()` and `updatePage()`.
|
||||
|
||||
---
|
||||
|
||||
## 3. wp_mail / sendmail Not Available in Container (FIXED)
|
||||
|
||||
**Problem:**
|
||||
The `mainwp` Docker container has no `sendmail` binary. Any `wp_mail()` call in CLI context throws a PHP fatal (sendmail process fails).
|
||||
|
||||
**Fix applied:**
|
||||
PHP ini override at `/usr/local/etc/php/conf.d/mcp-mail.ini`:
|
||||
```ini
|
||||
sendmail_path = /bin/true
|
||||
```
|
||||
|
||||
This routes all mail to `/dev/null` in CLI context. Web requests are unaffected (Apache/PHP-FPM reads the ini on startup).
|
||||
|
||||
Also deployed as a mu-plugin:
|
||||
`/var/www/html/wp-content/mu-plugins/null_sendmail.php`
|
||||
|
||||
```php
|
||||
if (PHP_SAPI === 'cli') {
|
||||
ini_set('sendmail_path', '/bin/true');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Standard CLI Script Header
|
||||
|
||||
Every PHP script that bootstraps WordPress for CLI use must include:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$_SERVER['HTTP_HOST'] = 'mainwp.asktam.net';
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
define('WP_ADMIN', true);
|
||||
define('DOING_CRON', true); // ← required for ElementorData CLI fix
|
||||
require '/var/www/html/wp-load.php';
|
||||
```
|
||||
|
||||
Without `DOING_CRON`, the ElementorData CLI fix does not activate and data will not accumulate correctly.
|
||||
|
||||
---
|
||||
|
||||
## 5. Calling Tools Directly in Scripts
|
||||
|
||||
To call MCP tools from a PHP CLI script:
|
||||
|
||||
```php
|
||||
$reg = new \AskTamMCP\MCP\Registry();
|
||||
$result = call_user_func($reg->getHandler('tool_name'), ['arg' => 'value']);
|
||||
```
|
||||
|
||||
Errors thrown by tools are PHP exceptions. Wrap in try/catch if needed:
|
||||
|
||||
```php
|
||||
try {
|
||||
$r = call_user_func($reg->getHandler('elementor_add_container'), [
|
||||
'post_id' => $pid,
|
||||
'settings' => ['background_color' => '#1e293b'],
|
||||
]);
|
||||
$container_id = $r['element_id'];
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Gitea Commits via Script
|
||||
|
||||
The `gitea_create_or_update_file` MCP tool sends `content` as a literal string — it does NOT read files from the VPS. Always provide the full file content directly in the `content` parameter.
|
||||
|
||||
For multi-file commits, use a Node.js script that reads files from `/tmp/` and calls the Gitea API via HTTPS.
|
||||
|
||||
---
|
||||
|
||||
## 7. Elementor Build — Complete Working Pattern
|
||||
|
||||
Full pattern for building a page with Elementor tools from a CLI script:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$_SERVER['HTTP_HOST'] = 'mainwp.asktam.net';
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
define('WP_ADMIN', true);
|
||||
define('DOING_CRON', true);
|
||||
require '/var/www/html/wp-load.php';
|
||||
|
||||
// Intercept wp_die (optional — turns fatal into exception)
|
||||
add_filter('wp_die_handler', function() {
|
||||
return function($msg, $title='', $args=[]) {
|
||||
$m = is_wp_error($msg) ? $msg->get_error_message() : strip_tags((string)$msg);
|
||||
throw new \RuntimeException("wp_die: $m");
|
||||
};
|
||||
}, 1);
|
||||
|
||||
$reg = new \AskTamMCP\MCP\Registry();
|
||||
|
||||
// 1. Create page (draft, no template yet)
|
||||
$pid = wp_insert_post([
|
||||
'post_title' => 'My Page',
|
||||
'post_status' => 'draft',
|
||||
'post_type' => 'page',
|
||||
'meta_input' => ['_elementor_edit_mode' => 'builder'],
|
||||
]);
|
||||
|
||||
// 2. Build with Elementor tools
|
||||
$hero = call_user_func($reg->getHandler('elementor_add_container'), [
|
||||
'post_id' => $pid,
|
||||
'settings' => ['background_color' => '#1e293b', 'min_height' => ['size' => 100, 'unit' => 'vh']],
|
||||
]);
|
||||
$hid = $hero['element_id'];
|
||||
|
||||
call_user_func($reg->getHandler('elementor_add_heading'), [
|
||||
'post_id' => $pid,
|
||||
'container_id' => $hid,
|
||||
'title' => 'Hello World',
|
||||
'tag' => 'h1',
|
||||
'settings' => ['title_color' => '#ffffff'],
|
||||
]);
|
||||
|
||||
// 3. Publish — NO page_template in wp_update_post
|
||||
wp_update_post(['ID' => $pid, 'post_status' => 'publish']);
|
||||
|
||||
// 4. Set template via meta AFTER publish
|
||||
update_post_meta($pid, '_wp_page_template', 'elementor-full-width');
|
||||
|
||||
// 5. Regenerate Elementor CSS
|
||||
if (class_exists('\Elementor\Core\Files\CSS\Post')) {
|
||||
(new \Elementor\Core\Files\CSS\Post($pid))->update();
|
||||
}
|
||||
|
||||
echo "Done: " . get_permalink($pid) . "\n";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Test Suite
|
||||
|
||||
Two test scripts on VPS at `/tmp/`:
|
||||
|
||||
| Script | Coverage | Expected |
|
||||
|---|---|---|
|
||||
| `test_93.php` | Original 93 tools | 74 OK / 2 test-data errors / 16 safe skips |
|
||||
| `test_new_tools.php` | 30 new tools | 24 OK / 3 test-data errors / 2 safe skips |
|
||||
|
||||
Run:
|
||||
```bash
|
||||
docker cp /tmp/test_93.php mainwp:/tmp/test_93.php
|
||||
docker exec mainwp php /tmp/test_93.php
|
||||
```
|
||||
|
||||
"test-data errors" = tools that need real data (an existing order, a real product ID) to test. Not bugs.
|
||||
"safe skips" = destructive tools (delete page content, etc.) skipped intentionally.
|
||||
|
||||
---
|
||||
|
||||
## 9. Key Files to Check Before Making Changes
|
||||
|
||||
| File | Why |
|
||||
|---|---|
|
||||
| `includes/Tools/ToolHandlers.php` | All 123 tools with schemas — check before adding a new tool |
|
||||
| `includes/MCP/Registry.php` | How tools are dispatched — check before changing routing |
|
||||
| `includes/Core/Auth.php` | Full auth flow — check before changing security |
|
||||
| `includes/Elementor/Data/ElementorData.php` | CLI cache fix — do not revert without understanding issue #1 |
|
||||
| `includes/Tools/PageTools.php` | Template fix — do not pass page_template to wp_update_post |
|
||||
| `includes/Elementor/Abilities/ElementorTools.php` | All 30 Elementor tool implementations |
|
||||
Reference in New Issue
Block a user