745 lines
24 KiB
Markdown
745 lines
24 KiB
Markdown
# IGNY8 WordPress Plugin - Complete Refactor Plan
|
|
|
|
**Created**: 2025-12-01
|
|
**Scope**: Simplify to one-way publishing only, remove all automatic sync, fix broken features
|
|
|
|
---
|
|
|
|
## 🎯 Refactor Goals
|
|
|
|
1. **One-Way Publishing Only**: IGNY8 → WordPress, no bidirectional sync
|
|
2. **Immediate Response**: WordPress returns all IDs right after post creation
|
|
3. **Clean UI**: Proper meta boxes for keywords, SEO, and tracking data
|
|
4. **Pure Taxonomies**: Cluster/sector as taxonomies only (remove post_meta duplication)
|
|
5. **Working Images**: Fix gallery image saving
|
|
6. **User Control**: Draft vs publish setting in WP admin
|
|
7. **Remove Complexity**: Delete all automatic sync, cron jobs, hooks
|
|
|
|
---
|
|
|
|
## 📋 Refactor Tasks
|
|
|
|
### Phase 1: Remove Automatic Sync (Clean Up)
|
|
|
|
#### Task 1.1: Delete Sync Hooks
|
|
**File**: `sync/hooks.php`
|
|
**Action**: Delete entire file
|
|
**Reason**: All automatic sync hooks removed
|
|
|
|
**Files to remove:**
|
|
```
|
|
sync/hooks.php (DELETE)
|
|
sync/post-sync.php (DELETE - bidirectional sync)
|
|
sync/taxonomy-sync.php (DELETE - bidirectional sync)
|
|
```
|
|
|
|
**Code to remove from other files:**
|
|
- Remove `require_once 'sync/hooks.php'` from main plugin file
|
|
- Remove all cron job registrations
|
|
- Remove all `save_post`, `publish_post`, `transition_post_status` hooks
|
|
|
|
---
|
|
|
|
#### Task 1.2: Remove Brief Meta Box
|
|
**File**: `admin/class-post-meta-boxes.php`
|
|
**Changes**:
|
|
```php
|
|
// REMOVE these lines from add_meta_boxes() method:
|
|
add_meta_box(
|
|
'igny8-planner-brief',
|
|
__('IGNY8 Planner Brief', 'igny8-bridge'),
|
|
array($this, 'render_planner_brief_box'),
|
|
$post_type,
|
|
'side',
|
|
'default'
|
|
);
|
|
|
|
// REMOVE entire method:
|
|
public function render_planner_brief_box($post) { ... }
|
|
|
|
// REMOVE AJAX handlers:
|
|
add_action('wp_ajax_igny8_fetch_planner_brief', array($this, 'fetch_planner_brief'));
|
|
add_action('wp_ajax_igny8_refresh_planner_task', array($this, 'refresh_planner_task'));
|
|
|
|
// REMOVE methods:
|
|
public function fetch_planner_brief() { ... }
|
|
public function refresh_planner_task() { ... }
|
|
```
|
|
|
|
**Reason**: No brief data exists in IGNY8
|
|
|
|
---
|
|
|
|
#### Task 1.3: Clean Up task_id References
|
|
**Investigation needed**: Determine if `_igny8_task_id` is:
|
|
- Writer task (remove completely)
|
|
- Celery task for async operations (keep for tracking)
|
|
|
|
**Action**: If writer task, remove all references to `_igny8_task_id`
|
|
|
|
---
|
|
|
|
### Phase 2: Fix Core Publishing
|
|
|
|
#### Task 2.1: Fix Gallery Images Function
|
|
**File**: `sync/igny8-to-wp.php`
|
|
**Current**: Line 290 calls `igny8_set_gallery_images()` but function is named `igny8_set_image_gallery()`
|
|
|
|
**Fix**:
|
|
```php
|
|
// Option 1: Rename function call
|
|
if (!empty($content_data['gallery_images'])) {
|
|
Igny8_Logger::info("{$log_prefix} STEP: Setting gallery with " . count($content_data['gallery_images']) . " images");
|
|
igny8_set_image_gallery($post_id, $content_data['gallery_images']); // Changed from igny8_set_gallery_images
|
|
}
|
|
|
|
// OR Option 2: Add alias function
|
|
function igny8_set_gallery_images($post_id, $gallery_images) {
|
|
return igny8_set_image_gallery($post_id, $gallery_images);
|
|
}
|
|
```
|
|
|
|
**Test**: Verify gallery images are saved to `_igny8_gallery_images` post_meta
|
|
|
|
---
|
|
|
|
#### Task 2.2: Fix Cluster/Sector Storage
|
|
**File**: `sync/igny8-to-wp.php`
|
|
**Current**: Lines 141-175 save cluster_id and sector_id as post_meta
|
|
|
|
**Remove these lines**:
|
|
```php
|
|
// REMOVE (lines ~163-175):
|
|
if (!empty($content_data['cluster_id'])) {
|
|
$post_data['meta_input']['_igny8_cluster_id'] = $content_data['cluster_id'];
|
|
}
|
|
|
|
if (!empty($content_data['sector_id'])) {
|
|
$post_data['meta_input']['_igny8_sector_id'] = $content_data['sector_id'];
|
|
}
|
|
```
|
|
|
|
**Keep only taxonomy assignment** (lines ~195-230):
|
|
```php
|
|
// KEEP: This correctly assigns taxonomies
|
|
if (!empty($content_data['cluster_id'])) {
|
|
$cluster_terms = get_terms(array(
|
|
'taxonomy' => 'igny8_clusters',
|
|
'meta_key' => '_igny8_cluster_id',
|
|
'meta_value' => $content_data['cluster_id'],
|
|
'hide_empty' => false
|
|
));
|
|
|
|
if (!is_wp_error($cluster_terms) && !empty($cluster_terms)) {
|
|
wp_set_post_terms($post_id, array($cluster_terms[0]->term_id), 'igny8_clusters');
|
|
}
|
|
}
|
|
// Same for sector...
|
|
```
|
|
|
|
**Issue**: This searches for terms by meta_key, but terms need to exist first!
|
|
|
|
**Better approach**:
|
|
```php
|
|
if (!empty($content_data['cluster_id'])) {
|
|
// Get cluster name from IGNY8 (need to send cluster_name in payload)
|
|
$cluster_name = $content_data['cluster_name'] ?? '';
|
|
|
|
if (!empty($cluster_name)) {
|
|
$term = wp_insert_term($cluster_name, 'igny8_clusters', array(
|
|
'slug' => sanitize_title($cluster_name)
|
|
));
|
|
|
|
if (!is_wp_error($term)) {
|
|
// Store IGNY8 cluster_id as term meta for future lookups
|
|
update_term_meta($term['term_id'], '_igny8_cluster_id', $content_data['cluster_id']);
|
|
wp_set_post_terms($post_id, array($term['term_id']), 'igny8_clusters');
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Backend change needed**: `wordpress_adapter.py` must send `cluster_name` and `sector_name` in payload
|
|
|
|
---
|
|
|
|
#### Task 2.3: Add Draft/Publish Setting
|
|
**File**: `admin/settings.php`
|
|
**Add new setting field**:
|
|
|
|
```php
|
|
// In settings registration (around line ~100):
|
|
add_settings_field(
|
|
'igny8_default_post_status',
|
|
__('Default Post Status', 'igny8-bridge'),
|
|
'igny8_render_default_post_status_field',
|
|
'igny8-settings',
|
|
'igny8_settings_section'
|
|
);
|
|
|
|
// Add field renderer:
|
|
function igny8_render_default_post_status_field() {
|
|
$status = get_option('igny8_default_post_status', 'draft');
|
|
?>
|
|
<fieldset>
|
|
<label>
|
|
<input type="radio" name="igny8_default_post_status" value="draft" <?php checked($status, 'draft'); ?>>
|
|
<?php _e('Draft - Save as draft for review', 'igny8-bridge'); ?>
|
|
</label><br>
|
|
<label>
|
|
<input type="radio" name="igny8_default_post_status" value="publish" <?php checked($status, 'publish'); ?>>
|
|
<?php _e('Publish - Publish immediately', 'igny8-bridge'); ?>
|
|
</label>
|
|
<p class="description">
|
|
<?php _e('Choose whether content from IGNY8 should be published immediately or saved as draft.', 'igny8-bridge'); ?>
|
|
</p>
|
|
</fieldset>
|
|
<?php
|
|
}
|
|
```
|
|
|
|
**File**: `sync/igny8-to-wp.php`
|
|
**Use setting in post creation** (line ~122):
|
|
|
|
```php
|
|
// OLD:
|
|
'post_status' => igny8_map_igny8_status_to_wp($content_data['status'] ?? 'draft'),
|
|
|
|
// NEW:
|
|
'post_status' => get_option('igny8_default_post_status', 'draft'),
|
|
```
|
|
|
|
---
|
|
|
|
#### Task 2.4: Return All Term IDs Immediately
|
|
**File**: `includes/class-igny8-rest-api.php`
|
|
**Modify `publish_content_to_wordpress()` return** (around line 615):
|
|
|
|
```php
|
|
// After post creation (line ~605), collect term IDs:
|
|
$term_ids = array(
|
|
'categories' => array(),
|
|
'tags' => array(),
|
|
'igny8_clusters' => array(),
|
|
'igny8_sectors' => array()
|
|
);
|
|
|
|
// Get assigned category IDs
|
|
$category_terms = wp_get_post_terms($post_id, 'category', array('fields' => 'ids'));
|
|
if (!is_wp_error($category_terms)) {
|
|
$term_ids['categories'] = $category_terms;
|
|
}
|
|
|
|
// Get assigned tag IDs
|
|
$tag_terms = wp_get_post_terms($post_id, 'post_tag', array('fields' => 'ids'));
|
|
if (!is_wp_error($tag_terms)) {
|
|
$term_ids['tags'] = $tag_terms;
|
|
}
|
|
|
|
// Get assigned cluster IDs
|
|
$cluster_terms = wp_get_post_terms($post_id, 'igny8_clusters', array('fields' => 'ids'));
|
|
if (!is_wp_error($cluster_terms)) {
|
|
$term_ids['igny8_clusters'] = $cluster_terms;
|
|
}
|
|
|
|
// Get assigned sector IDs
|
|
$sector_terms = wp_get_post_terms($post_id, 'igny8_sectors', array('fields' => 'ids'));
|
|
if (!is_wp_error($sector_terms)) {
|
|
$term_ids['igny8_sectors'] = $sector_terms;
|
|
}
|
|
|
|
// Return enhanced response:
|
|
return $this->build_unified_response(
|
|
true,
|
|
array(
|
|
'post_id' => $post_id,
|
|
'post_url' => get_permalink($post_id),
|
|
'post_status' => get_post_status($post_id),
|
|
'content_id' => $content_id,
|
|
'task_id' => $task_id,
|
|
'term_ids' => $term_ids // NEW
|
|
),
|
|
'Content successfully published to WordPress',
|
|
null,
|
|
null,
|
|
201
|
|
);
|
|
```
|
|
|
|
**Backend change needed**: `wordpress_adapter.py` must capture and save `term_ids` from response
|
|
|
|
---
|
|
|
|
### Phase 3: Add Custom Meta Boxes
|
|
|
|
#### Task 3.1: Add IGNY8 Keywords Meta Box
|
|
**File**: `admin/class-post-meta-boxes.php`
|
|
**Add meta box registration**:
|
|
|
|
```php
|
|
public function add_meta_boxes() {
|
|
$post_types = array('post', 'page', 'product');
|
|
|
|
foreach ($post_types as $post_type) {
|
|
// NEW: IGNY8 Keywords
|
|
add_meta_box(
|
|
'igny8-keywords',
|
|
__('IGNY8 Keywords', 'igny8-bridge'),
|
|
array($this, 'render_keywords_box'),
|
|
$post_type,
|
|
'side',
|
|
'high'
|
|
);
|
|
|
|
// NEW: IGNY8 SEO
|
|
add_meta_box(
|
|
'igny8-seo',
|
|
__('IGNY8 SEO', 'igny8-bridge'),
|
|
array($this, 'render_seo_box'),
|
|
$post_type,
|
|
'normal',
|
|
'high'
|
|
);
|
|
|
|
// NEW: IGNY8 Sync Data (read-only)
|
|
add_meta_box(
|
|
'igny8-sync-data',
|
|
__('IGNY8 Sync Data', 'igny8-bridge'),
|
|
array($this, 'render_sync_data_box'),
|
|
$post_type,
|
|
'side',
|
|
'low'
|
|
);
|
|
|
|
// KEEP: IGNY8 Optimizer (existing)
|
|
add_meta_box(
|
|
'igny8-optimizer',
|
|
__('IGNY8 Optimizer', 'igny8-bridge'),
|
|
array($this, 'render_optimizer_box'),
|
|
$post_type,
|
|
'side',
|
|
'default'
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Add render methods**:
|
|
|
|
```php
|
|
/**
|
|
* Render Keywords meta box
|
|
*/
|
|
public function render_keywords_box($post) {
|
|
$primary_keyword = get_post_meta($post->ID, '_igny8_primary_keyword', true);
|
|
$secondary_keywords = get_post_meta($post->ID, '_igny8_secondary_keywords', true);
|
|
|
|
// Decode JSON if needed
|
|
if (is_string($secondary_keywords)) {
|
|
$secondary_keywords = json_decode($secondary_keywords, true);
|
|
}
|
|
if (!is_array($secondary_keywords)) {
|
|
$secondary_keywords = array();
|
|
}
|
|
|
|
wp_nonce_field('igny8_keywords_nonce', 'igny8_keywords_nonce');
|
|
?>
|
|
<div class="igny8-keywords-box">
|
|
<p>
|
|
<label for="igny8_primary_keyword">
|
|
<strong><?php _e('Primary Keyword', 'igny8-bridge'); ?></strong>
|
|
</label>
|
|
<input type="text"
|
|
id="igny8_primary_keyword"
|
|
name="igny8_primary_keyword"
|
|
value="<?php echo esc_attr($primary_keyword); ?>"
|
|
class="widefat"
|
|
placeholder="<?php _e('Enter primary keyword', 'igny8-bridge'); ?>">
|
|
</p>
|
|
|
|
<p>
|
|
<label for="igny8_secondary_keywords">
|
|
<strong><?php _e('Secondary Keywords', 'igny8-bridge'); ?></strong>
|
|
</label>
|
|
<input type="text"
|
|
id="igny8_secondary_keywords"
|
|
name="igny8_secondary_keywords"
|
|
value="<?php echo esc_attr(implode(', ', $secondary_keywords)); ?>"
|
|
class="widefat"
|
|
placeholder="<?php _e('keyword1, keyword2, keyword3', 'igny8-bridge'); ?>">
|
|
<span class="description"><?php _e('Separate keywords with commas', 'igny8-bridge'); ?></span>
|
|
</p>
|
|
|
|
<?php if (!empty($primary_keyword) || !empty($secondary_keywords)) : ?>
|
|
<p class="description">
|
|
<em><?php _e('✅ These keywords were set by IGNY8', 'igny8-bridge'); ?></em>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render SEO meta box
|
|
*/
|
|
public function render_seo_box($post) {
|
|
$meta_title = get_post_meta($post->ID, '_igny8_meta_title', true);
|
|
$meta_description = get_post_meta($post->ID, '_igny8_meta_description', true);
|
|
|
|
wp_nonce_field('igny8_seo_nonce', 'igny8_seo_nonce');
|
|
?>
|
|
<div class="igny8-seo-box">
|
|
<p>
|
|
<label for="igny8_meta_title">
|
|
<strong><?php _e('SEO Title', 'igny8-bridge'); ?></strong>
|
|
</label>
|
|
<input type="text"
|
|
id="igny8_meta_title"
|
|
name="igny8_meta_title"
|
|
value="<?php echo esc_attr($meta_title); ?>"
|
|
class="widefat"
|
|
placeholder="<?php _e('Enter SEO title', 'igny8-bridge'); ?>">
|
|
<span class="description"><?php _e('Recommended: 50-60 characters', 'igny8-bridge'); ?></span>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="igny8_meta_description">
|
|
<strong><?php _e('SEO Meta Description', 'igny8-bridge'); ?></strong>
|
|
</label>
|
|
<textarea id="igny8_meta_description"
|
|
name="igny8_meta_description"
|
|
rows="3"
|
|
class="widefat"
|
|
placeholder="<?php _e('Enter meta description', 'igny8-bridge'); ?>"><?php echo esc_textarea($meta_description); ?></textarea>
|
|
<span class="description"><?php _e('Recommended: 150-160 characters', 'igny8-bridge'); ?></span>
|
|
</p>
|
|
|
|
<?php if (!empty($meta_title) || !empty($meta_description)) : ?>
|
|
<p class="description">
|
|
<em><?php _e('✅ These SEO fields were set by IGNY8', 'igny8-bridge'); ?></em>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render Sync Data meta box (read-only)
|
|
*/
|
|
public function render_sync_data_box($post) {
|
|
$content_id = get_post_meta($post->ID, '_igny8_content_id', true);
|
|
$content_type = get_post_meta($post->ID, '_igny8_content_type', true);
|
|
$content_structure = get_post_meta($post->ID, '_igny8_content_structure', true);
|
|
$cluster_id = get_post_meta($post->ID, '_igny8_cluster_id', true);
|
|
$sector_id = get_post_meta($post->ID, '_igny8_sector_id', true);
|
|
|
|
?>
|
|
<div class="igny8-sync-data-box">
|
|
<table class="widefat striped">
|
|
<tbody>
|
|
<?php if ($content_id) : ?>
|
|
<tr>
|
|
<td><strong><?php _e('Content ID', 'igny8-bridge'); ?></strong></td>
|
|
<td><code><?php echo esc_html($content_id); ?></code></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($content_type) : ?>
|
|
<tr>
|
|
<td><strong><?php _e('Content Type', 'igny8-bridge'); ?></strong></td>
|
|
<td><?php echo esc_html($content_type); ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($content_structure) : ?>
|
|
<tr>
|
|
<td><strong><?php _e('Structure', 'igny8-bridge'); ?></strong></td>
|
|
<td><?php echo esc_html($content_structure); ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($cluster_id) : ?>
|
|
<tr>
|
|
<td><strong><?php _e('Cluster ID', 'igny8-bridge'); ?></strong></td>
|
|
<td><code><?php echo esc_html($cluster_id); ?></code></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($sector_id) : ?>
|
|
<tr>
|
|
<td><strong><?php _e('Sector ID', 'igny8-bridge'); ?></strong></td>
|
|
<td><code><?php echo esc_html($sector_id); ?></code></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<?php if ($content_id) : ?>
|
|
<p class="description">
|
|
<em><?php _e('This post was published from IGNY8', 'igny8-bridge'); ?></em>
|
|
</p>
|
|
<?php else : ?>
|
|
<p class="description">
|
|
<em><?php _e('This post was not created by IGNY8', 'igny8-bridge'); ?></em>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
}
|
|
```
|
|
|
|
**Add save handlers**:
|
|
|
|
```php
|
|
/**
|
|
* Save keywords when post is saved
|
|
*/
|
|
public function save_keywords($post_id) {
|
|
// Check nonce
|
|
if (!isset($_POST['igny8_keywords_nonce']) || !wp_verify_nonce($_POST['igny8_keywords_nonce'], 'igny8_keywords_nonce')) {
|
|
return;
|
|
}
|
|
|
|
// Check autosave
|
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
|
return;
|
|
}
|
|
|
|
// Check permissions
|
|
if (!current_user_can('edit_post', $post_id)) {
|
|
return;
|
|
}
|
|
|
|
// Save primary keyword
|
|
if (isset($_POST['igny8_primary_keyword'])) {
|
|
update_post_meta($post_id, '_igny8_primary_keyword', sanitize_text_field($_POST['igny8_primary_keyword']));
|
|
}
|
|
|
|
// Save secondary keywords
|
|
if (isset($_POST['igny8_secondary_keywords'])) {
|
|
$keywords = sanitize_text_field($_POST['igny8_secondary_keywords']);
|
|
$keywords_array = array_map('trim', explode(',', $keywords));
|
|
$keywords_array = array_filter($keywords_array); // Remove empty
|
|
update_post_meta($post_id, '_igny8_secondary_keywords', json_encode($keywords_array));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save SEO fields when post is saved
|
|
*/
|
|
public function save_seo($post_id) {
|
|
// Check nonce
|
|
if (!isset($_POST['igny8_seo_nonce']) || !wp_verify_nonce($_POST['igny8_seo_nonce'], 'igny8_seo_nonce')) {
|
|
return;
|
|
}
|
|
|
|
// Check autosave
|
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
|
return;
|
|
}
|
|
|
|
// Check permissions
|
|
if (!current_user_can('edit_post', $post_id)) {
|
|
return;
|
|
}
|
|
|
|
// Save meta title
|
|
if (isset($_POST['igny8_meta_title'])) {
|
|
$meta_title = sanitize_text_field($_POST['igny8_meta_title']);
|
|
update_post_meta($post_id, '_igny8_meta_title', $meta_title);
|
|
|
|
// Also update SEO plugin fields
|
|
update_post_meta($post_id, '_yoast_wpseo_title', $meta_title);
|
|
update_post_meta($post_id, '_seopress_titles_title', $meta_title);
|
|
update_post_meta($post_id, '_aioseo_title', $meta_title);
|
|
}
|
|
|
|
// Save meta description
|
|
if (isset($_POST['igny8_meta_description'])) {
|
|
$meta_description = sanitize_textarea_field($_POST['igny8_meta_description']);
|
|
update_post_meta($post_id, '_igny8_meta_description', $meta_description);
|
|
|
|
// Also update SEO plugin fields
|
|
update_post_meta($post_id, '_yoast_wpseo_metadesc', $meta_description);
|
|
update_post_meta($post_id, '_seopress_titles_desc', $meta_description);
|
|
update_post_meta($post_id, '_aioseo_description', $meta_description);
|
|
}
|
|
}
|
|
|
|
// Register save handlers in constructor:
|
|
public function __construct() {
|
|
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
|
|
add_action('save_post', array($this, 'save_keywords'), 10, 1);
|
|
add_action('save_post', array($this, 'save_seo'), 10, 1);
|
|
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
|
|
|
|
// Keep optimizer AJAX handler
|
|
add_action('wp_ajax_igny8_create_optimizer_job', array($this, 'create_optimizer_job'));
|
|
add_action('wp_ajax_igny8_get_optimizer_status', array($this, 'get_optimizer_status'));
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Phase 4: Backend Changes (IGNY8 Django)
|
|
|
|
#### Task 4.1: Send cluster_name and sector_name
|
|
**File**: `backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py`
|
|
**Add to payload** (around line 172):
|
|
|
|
```python
|
|
# Current:
|
|
if hasattr(content, 'cluster') and content.cluster:
|
|
content_data['cluster_id'] = content.cluster.id
|
|
optional_fields.append('cluster_id')
|
|
|
|
# NEW:
|
|
if hasattr(content, 'cluster') and content.cluster:
|
|
content_data['cluster_id'] = content.cluster.id
|
|
content_data['cluster_name'] = content.cluster.name # ADD THIS
|
|
optional_fields.append('cluster_id')
|
|
|
|
if hasattr(content, 'sector') and content.sector:
|
|
content_data['sector_id'] = content.sector.id
|
|
content_data['sector_name'] = content.sector.name # ADD THIS
|
|
optional_fields.append('sector_id')
|
|
```
|
|
|
|
---
|
|
|
|
#### Task 4.2: Capture and Save term_ids from Response
|
|
**File**: `backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py`
|
|
**Modify response handling** (around line 300):
|
|
|
|
```python
|
|
if response.status_code == 201:
|
|
wp_data = response.json().get('data', {})
|
|
logger.info(f"[WordPressAdapter._publish_via_api_key] ✅ Success! WordPress post created: post_id={wp_data.get('post_id')}, url={wp_data.get('post_url')}")
|
|
|
|
# NEW: Extract term_ids
|
|
term_ids = wp_data.get('term_ids', {})
|
|
|
|
return {
|
|
'success': True,
|
|
'external_id': str(wp_data.get('post_id')),
|
|
'url': wp_data.get('post_url'),
|
|
'published_at': datetime.now(),
|
|
'metadata': {
|
|
'post_id': wp_data.get('post_id'),
|
|
'status': destination_config.get('status', 'publish'),
|
|
'term_ids': term_ids # NEW: Save term mappings
|
|
}
|
|
}
|
|
```
|
|
|
|
**Optional**: Store term_ids in `content.external_metadata` JSON field for future reference
|
|
|
|
---
|
|
|
|
## 🗂️ File Structure After Refactor
|
|
|
|
```
|
|
igny8-wp-plugin/
|
|
├── igny8-bridge.php (main plugin file)
|
|
├── uninstall.php
|
|
├── admin/
|
|
│ ├── class-admin.php
|
|
│ ├── class-admin-columns.php
|
|
│ ├── class-post-meta-boxes.php ✅ UPDATED (new meta boxes, remove brief)
|
|
│ ├── settings.php ✅ UPDATED (add draft/publish setting)
|
|
│ └── assets/
|
|
├── includes/
|
|
│ ├── class-igny8-api.php
|
|
│ ├── class-igny8-rest-api.php ✅ UPDATED (return term_ids)
|
|
│ ├── class-igny8-logger.php
|
|
│ ├── class-igny8-webhooks.php (KEEP for future)
|
|
│ └── functions.php ✅ UPDATED (ensure taxonomies registered)
|
|
├── sync/
|
|
│ ├── igny8-to-wp.php ✅ UPDATED (fix gallery, remove post_meta for cluster/sector)
|
|
│ ├── hooks.php ❌ DELETE
|
|
│ ├── post-sync.php ❌ DELETE
|
|
│ └── taxonomy-sync.php ❌ DELETE
|
|
├── data/ (keep for site collection/link graph)
|
|
└── tests/ (keep for testing)
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Testing Checklist
|
|
|
|
### After Refactor, Test:
|
|
|
|
1. **Publish from IGNY8**:
|
|
- ✅ Post created in WordPress
|
|
- ✅ Title, content, excerpt correct
|
|
- ✅ Categories assigned correctly
|
|
- ✅ Tags assigned correctly
|
|
- ✅ Featured image downloaded and set
|
|
- ✅ Gallery images downloaded and saved to post_meta
|
|
- ✅ Cluster assigned as taxonomy (no post_meta)
|
|
- ✅ Sector assigned as taxonomy (no post_meta)
|
|
- ✅ Primary keyword saved to `_igny8_primary_keyword`
|
|
- ✅ Secondary keywords saved to `_igny8_secondary_keywords` (JSON)
|
|
- ✅ Meta title saved to SEO plugin fields
|
|
- ✅ Meta description saved to SEO plugin fields
|
|
|
|
2. **WordPress Response**:
|
|
- ✅ Returns post_id immediately
|
|
- ✅ Returns post_url immediately
|
|
- ✅ Returns term_ids for all taxonomies
|
|
- ✅ IGNY8 backend saves external_id, external_url, status='published'
|
|
|
|
3. **WordPress Editor UI**:
|
|
- ✅ "IGNY8 Keywords" meta box shows primary + secondary keywords (editable)
|
|
- ✅ "IGNY8 SEO" meta box shows meta_title + meta_description (editable)
|
|
- ✅ "IGNY8 Sync Data" meta box shows all tracking fields (read-only)
|
|
- ✅ NO "IGNY8 Planner Brief" meta box
|
|
- ✅ Cluster and sector show in taxonomy sidebars
|
|
- ✅ Editing keywords/SEO saves correctly
|
|
|
|
4. **WordPress Settings**:
|
|
- ✅ "Default Post Status" option exists (draft/publish radio)
|
|
- ✅ Changing setting affects next publish
|
|
|
|
5. **No Automatic Sync**:
|
|
- ✅ Editing post in WordPress does NOT trigger API call to IGNY8
|
|
- ✅ Publishing post in WordPress does NOT trigger sync
|
|
- ✅ No cron jobs running
|
|
|
|
---
|
|
|
|
## 📝 Summary of Changes
|
|
|
|
### Removed:
|
|
- ❌ All automatic sync hooks (save_post, publish_post, etc.)
|
|
- ❌ Bidirectional sync files (post-sync.php, taxonomy-sync.php, hooks.php)
|
|
- ❌ Brief meta box (no data in IGNY8)
|
|
- ❌ Cron jobs for sync
|
|
- ❌ Post_meta storage for cluster_id and sector_id
|
|
|
|
### Fixed:
|
|
- ✅ Gallery images function name (`igny8_set_gallery_images` → `igny8_set_image_gallery`)
|
|
- ✅ Cluster/sector stored ONLY as taxonomies (with term_meta for IGNY8 ID mapping)
|
|
|
|
### Added:
|
|
- ✅ "IGNY8 Keywords" meta box (primary_keyword, secondary_keywords)
|
|
- ✅ "IGNY8 SEO" meta box (meta_title, meta_description)
|
|
- ✅ "IGNY8 Sync Data" meta box (read-only tracking fields)
|
|
- ✅ WP admin setting: "Default Post Status" (draft/publish)
|
|
- ✅ WordPress returns term_ids in publish response
|
|
- ✅ Backend sends cluster_name and sector_name for taxonomy creation
|
|
- ✅ Backend saves term_ids from WordPress response
|
|
|
|
---
|
|
|
|
## 🚀 Implementation Order
|
|
|
|
1. **Phase 1** (Clean up): Remove sync files, hooks, brief meta box
|
|
2. **Phase 2** (Fix core): Gallery images, cluster/sector, draft setting, response enhancement
|
|
3. **Phase 3** (Add UI): New meta boxes for keywords, SEO, sync data
|
|
4. **Phase 4** (Backend): Update WordPress adapter to send names and capture term_ids
|
|
|
|
**Estimated time**: 4-6 hours
|
|
**Risk level**: Low (mostly removing code, fixing bugs, adding UI)
|
|
**Testing requirement**: High (verify all fields save correctly)
|