updates
This commit is contained in:
@@ -1,239 +0,0 @@
|
||||
# Content Publishing Fixes Applied
|
||||
|
||||
**Date:** November 29, 2025
|
||||
**Issue:** Only title was being published to WordPress, not the full content_html
|
||||
**Root Cause:** WordPress REST endpoint was fetching from wrong API endpoint (Tasks model instead of Content model) + Field name mismatches
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue Identified
|
||||
|
||||
**Problem:** WordPress posts were created with only the title, no content body.
|
||||
|
||||
**Root Cause Analysis:**
|
||||
1. WordPress REST endpoint (`class-igny8-rest-api.php`) was making an API callback to `/writer/tasks/{task_id}/`
|
||||
2. This endpoint returns the **Tasks** model, which does NOT have a `content_html` field
|
||||
3. Tasks model only has: `title`, `description`, `keywords` (no actual content)
|
||||
4. Meanwhile, IGNY8 backend was already sending full `content_html` in the POST body
|
||||
5. WordPress was ignoring the POST body and using the API callback response instead
|
||||
|
||||
---
|
||||
|
||||
## Fixes Applied
|
||||
|
||||
### Fix #1: WordPress REST Endpoint (CRITICAL)
|
||||
|
||||
**File:** `includes/class-igny8-rest-api.php`
|
||||
**Function:** `publish_content_to_wordpress()`
|
||||
**Lines Modified:** 460-597
|
||||
|
||||
**What Changed:**
|
||||
- ✅ **REMOVED** 80+ lines of API callback logic (lines 507-545)
|
||||
- ✅ **REMOVED** call to `/writer/tasks/{task_id}/` endpoint
|
||||
- ✅ **CHANGED** to parse POST body directly: `$content_data = $request->get_json_params()`
|
||||
- ✅ **ADDED** validation for required fields: `content_id`, `title`, `content_html`
|
||||
- ✅ **ADDED** debug logging when `IGNY8_DEBUG` flag is defined
|
||||
|
||||
**Before:**
|
||||
```php
|
||||
// WordPress was making a redundant API call
|
||||
$response = $api->get("/writer/tasks/{$task_id}/");
|
||||
$content_data = $response['data'] ?? array(); // ❌ This had NO content_html
|
||||
```
|
||||
|
||||
**After:**
|
||||
```php
|
||||
// WordPress now uses the data IGNY8 already sent
|
||||
$content_data = $request->get_json_params(); // ✅ This has content_html
|
||||
```
|
||||
|
||||
**Impact:** WordPress now receives and uses the full `content_html` field sent by IGNY8 backend.
|
||||
|
||||
---
|
||||
|
||||
### Fix #2: IGNY8 Backend Payload (Field Name Corrections)
|
||||
|
||||
**File:** `backend/igny8_core/tasks/wordpress_publishing.py`
|
||||
**Function:** `publish_content_to_wordpress()`
|
||||
**Lines Modified:** 54-89
|
||||
|
||||
**Field Name Fixes:**
|
||||
|
||||
| ❌ Old (Wrong) | ✅ New (Correct) | Reason |
|
||||
|---|---|---|
|
||||
| `content.brief` | Generate from `content_html` | Content model has no `brief` field |
|
||||
| `content.author.email` | `None` | Content model has no `author` field |
|
||||
| `content.published_at` | `None` | Content model has no `published_at` field |
|
||||
| `getattr(content, 'seo_title', '')` | `content.meta_title or ''` | Correct field is `meta_title` |
|
||||
| `getattr(content, 'seo_description', '')` | `content.meta_description or ''` | Correct field is `meta_description` |
|
||||
| `getattr(content, 'focus_keywords', [])` | `content.secondary_keywords or []` | Correct field is `secondary_keywords` |
|
||||
| `content.featured_image.url` | `None` | Content model has no `featured_image` field |
|
||||
| `content.sectors.all()` | Empty array | Content has `sector` (ForeignKey), not `sectors` (many-to-many) |
|
||||
| `content.clusters.all()` | Empty array | Content has `cluster` (ForeignKey), not `clusters` (many-to-many) |
|
||||
| `getattr(content, 'tags', [])` | Empty array | Content model has no `tags` field |
|
||||
|
||||
**New Fields Added:**
|
||||
- ✅ `primary_keyword`: `content.primary_keyword or ''`
|
||||
- ✅ `cluster_id`: `content.cluster.id if content.cluster else None`
|
||||
- ✅ `sector_id`: `content.sector.id if content.sector else None`
|
||||
|
||||
**Excerpt Generation:**
|
||||
```python
|
||||
# Generate excerpt from content_html (Content model has no 'brief' field)
|
||||
excerpt = ''
|
||||
if content.content_html:
|
||||
from django.utils.html import strip_tags
|
||||
excerpt = strip_tags(content.content_html)[:150].strip()
|
||||
if len(content.content_html) > 150:
|
||||
excerpt += '...'
|
||||
```
|
||||
|
||||
**Impact:** Payload now uses fields that actually exist on Content model, preventing AttributeErrors.
|
||||
|
||||
---
|
||||
|
||||
## Content Model Structure (Reference)
|
||||
|
||||
**File:** `backend/igny8_core/business/content/models.py`
|
||||
**Model:** `Content(SiteSectorBaseModel)`
|
||||
|
||||
### Fields That Exist ✅
|
||||
- `title` (CharField)
|
||||
- `content_html` (TextField) ← **The actual content**
|
||||
- `meta_title` (CharField) ← SEO title
|
||||
- `meta_description` (TextField) ← SEO description
|
||||
- `primary_keyword` (CharField)
|
||||
- `secondary_keywords` (JSONField)
|
||||
- `cluster` (ForeignKey to Clusters)
|
||||
- `content_type` (CharField: post/page/product/taxonomy)
|
||||
- `content_structure` (CharField: article/guide/etc)
|
||||
- `status` (CharField: draft/review/published)
|
||||
- `source` (CharField: igny8/wordpress)
|
||||
- `external_id`, `external_url`, `external_type`, `sync_status`
|
||||
- `created_at`, `updated_at` (from base model)
|
||||
- `account`, `site`, `sector` (from SiteSectorBaseModel)
|
||||
|
||||
### Fields That Do NOT Exist ❌
|
||||
- ❌ `brief` or `excerpt`
|
||||
- ❌ `author`
|
||||
- ❌ `published_at`
|
||||
- ❌ `featured_image`
|
||||
- ❌ `seo_title` (it's `meta_title`)
|
||||
- ❌ `seo_description` (it's `meta_description`)
|
||||
- ❌ `focus_keywords` (it's `secondary_keywords`)
|
||||
- ❌ `sectors` (many-to-many)
|
||||
- ❌ `clusters` (many-to-many)
|
||||
- ❌ `tags`
|
||||
|
||||
---
|
||||
|
||||
## WordPress Function Already Handles content_html Correctly
|
||||
|
||||
**File:** `sync/igny8-to-wp.php`
|
||||
**Function:** `igny8_create_wordpress_post_from_task()`
|
||||
**Lines:** 73-200
|
||||
|
||||
This function was already correctly implemented:
|
||||
|
||||
```php
|
||||
// Stage 1 Schema: accept content_html (new) or content (legacy fallback)
|
||||
$content_html = $content_data['content_html'] ?? $content_data['content'] ?? '';
|
||||
|
||||
// ...
|
||||
|
||||
$post_data = array(
|
||||
'post_title' => sanitize_text_field($content_data['title'] ?? 'Untitled'),
|
||||
'post_content' => wp_kses_post($content_html), // ✅ Uses content_html
|
||||
'post_excerpt' => sanitize_text_field($excerpt),
|
||||
// ...
|
||||
);
|
||||
|
||||
$post_id = wp_insert_post($post_data);
|
||||
```
|
||||
|
||||
**No changes needed** - this function properly extracts `content_html` and creates the WordPress post.
|
||||
|
||||
---
|
||||
|
||||
## Data Flow (Fixed)
|
||||
|
||||
### Before Fix ❌
|
||||
```
|
||||
IGNY8 Backend
|
||||
├─ Sends POST with content_html ✓
|
||||
└─ WordPress receives it ✓
|
||||
├─ Ignores POST body ❌
|
||||
├─ Calls /writer/tasks/{id}/ ❌
|
||||
└─ Gets Tasks model (no content_html) ❌
|
||||
└─ Creates post with only title ❌
|
||||
```
|
||||
|
||||
### After Fix ✅
|
||||
```
|
||||
IGNY8 Backend
|
||||
├─ Sends POST with content_html ✓
|
||||
└─ WordPress receives it ✓
|
||||
├─ Parses POST body ✓
|
||||
├─ Validates content_html present ✓
|
||||
└─ Creates post with full content ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
To verify the fixes work:
|
||||
|
||||
1. ✅ Create a Content object in IGNY8 with full `content_html`
|
||||
2. ✅ Ensure Content has: `title`, `content_html`, `meta_title`, `meta_description`, `cluster`, `sector`
|
||||
3. ✅ Trigger `publish_content_to_wordpress` Celery task
|
||||
4. ✅ Verify WordPress receives full payload with `content_html`
|
||||
5. ✅ Confirm WordPress post created with:
|
||||
- Full content body (not just title)
|
||||
- Correct SEO metadata
|
||||
- Cluster and sector IDs stored
|
||||
6. ✅ Check WordPress postmeta for:
|
||||
- `_igny8_content_id`
|
||||
- `_igny8_task_id`
|
||||
- `_igny8_cluster_id`
|
||||
- `_igny8_sector_id`
|
||||
|
||||
---
|
||||
|
||||
## Debug Logging
|
||||
|
||||
To enable verbose logging, add to WordPress `wp-config.php`:
|
||||
|
||||
```php
|
||||
define('IGNY8_DEBUG', true);
|
||||
define('WP_DEBUG', true);
|
||||
define('WP_DEBUG_LOG', true);
|
||||
```
|
||||
|
||||
This will log:
|
||||
- Content ID received
|
||||
- Title received
|
||||
- Content HTML length
|
||||
- All REST API responses
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Files Modified:**
|
||||
1. `includes/class-igny8-rest-api.php` - WordPress REST endpoint
|
||||
2. `backend/igny8_core/tasks/wordpress_publishing.py` - IGNY8 backend payload
|
||||
|
||||
**Core Changes:**
|
||||
1. WordPress now uses POST body data instead of making redundant API call
|
||||
2. IGNY8 backend uses correct Content model field names
|
||||
3. Excerpt generated from content_html automatically
|
||||
4. Cluster and sector sent as IDs, not arrays
|
||||
|
||||
**Result:** Full content (including HTML body) now publishes to WordPress correctly.
|
||||
|
||||
---
|
||||
|
||||
**Generated:** 2025-11-29
|
||||
**Status:** FIXES APPLIED - Ready for testing
|
||||
**Priority:** HIGH - Core functionality restored
|
||||
Reference in New Issue
Block a user