Files
igny8/igny8-wp-plugin/docs/FIXES-APPLIED-CONTENT-PUBLISHING.md
2025-12-01 11:02:51 +05:00

7.7 KiB

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:

// 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:

// 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:

# 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:

// 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:

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