This commit is contained in:
alorig
2025-12-01 09:32:06 +05:00
parent aeaac01990
commit 71a38435b1
46 changed files with 75 additions and 17130 deletions

View File

@@ -1,42 +0,0 @@
<?php
/**
* WordPress Hooks Registration
*
* Registers all WordPress hooks for synchronization
*
* @package Igny8Bridge
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// Load sync class
require_once IGNY8_BRIDGE_PLUGIN_DIR . 'sync/post-sync.php';
/**
* Register WordPress hooks for IGNY8 sync
*/
function igny8_register_sync_hooks() {
// WordPress → IGNY8 hooks
add_action('save_post', 'igny8_sync_post_status_to_igny8', 10, 3);
add_action('publish_post', 'igny8_update_keywords_on_post_publish', 10, 1);
add_action('publish_page', 'igny8_update_keywords_on_post_publish', 10, 1);
add_action('draft_to_publish', 'igny8_update_keywords_on_post_publish', 10, 1);
add_action('future_to_publish', 'igny8_update_keywords_on_post_publish', 10, 1);
add_action('transition_post_status', 'igny8_sync_post_status_transition', 10, 3);
// Cron hooks
add_action('igny8_sync_post_statuses', 'igny8_cron_sync_post_statuses');
add_action('igny8_sync_site_data', 'igny8_cron_sync_site_data');
add_action('igny8_sync_from_igny8', 'igny8_cron_sync_from_igny8');
add_action('igny8_sync_taxonomies', 'igny8_cron_sync_taxonomies');
add_action('igny8_sync_keywords', 'igny8_cron_sync_keywords');
add_action('igny8_full_site_scan', 'igny8_cron_full_site_scan');
add_action('igny8_sync_site_structure', 'igny8_sync_site_structure_to_backend');
}
// Register hooks
igny8_register_sync_hooks();

File diff suppressed because it is too large Load Diff

View File

@@ -1,366 +0,0 @@
<?php
/**
* Post Synchronization Functions
*
* Handles WordPress → IGNY8 post synchronization
*
* @package Igny8Bridge
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Sync WordPress post status to IGNY8 when post is saved
*
* @param int $post_id Post ID
* @param WP_Post $post Post object
* @param bool $update Whether this is an update
*/
function igny8_sync_post_status_to_igny8($post_id, $post, $update) {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return;
}
// Skip autosaves and revisions
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (wp_is_post_revision($post_id)) {
return;
}
// Only sync IGNY8-managed posts
if (!igny8_is_igny8_managed_post($post_id)) {
return;
}
// Get task ID
$task_id = get_post_meta($post_id, '_igny8_task_id', true);
if (!$task_id) {
return;
}
// Get post status
$post_status = $post->post_status;
// Map WordPress status to IGNY8 task status
$task_status = igny8_map_wp_status_to_igny8($post_status);
// Sync to IGNY8 API
$api = new Igny8API();
// Get content_id if available
$content_id = get_post_meta($post_id, '_igny8_content_id', true);
$update_data = array(
'status' => $task_status,
'assigned_post_id' => $post_id,
'post_url' => get_permalink($post_id),
'wordpress_status' => $post_status, // Actual WordPress status
'synced_at' => current_time('mysql')
);
// Include content_id if available
if ($content_id) {
$update_data['content_id'] = $content_id;
}
$response = $api->put("/writer/tasks/{$task_id}/", $update_data);
if ($response['success']) {
// Update WordPress status in meta for IGNY8 to read
update_post_meta($post_id, '_igny8_wordpress_status', $post_status);
update_post_meta($post_id, '_igny8_last_synced', current_time('mysql'));
error_log("IGNY8: Synced post {$post_id} status ({$post_status}) to task {$task_id}");
// Send status webhook to IGNY8 backend
igny8_send_status_webhook($post_id, array('content_id' => $content_id), $post_status);
} else {
error_log("IGNY8: Failed to sync post status: " . ($response['error'] ?? 'Unknown error'));
}
}
/**
* Update keyword status when WordPress post is published
*
* @param int $post_id Post ID
*/
function igny8_update_keywords_on_post_publish($post_id) {
// Get task ID from post meta
$task_id = get_post_meta($post_id, '_igny8_task_id', true);
if (!$task_id) {
return;
}
$api = new Igny8API();
// Get task details to find associated cluster/keywords
$task_response = $api->get("/writer/tasks/{$task_id}/");
if (!$task_response['success']) {
return;
}
$task = $task_response['data'];
$cluster_id = $task['cluster_id'] ?? null;
if ($cluster_id) {
// Get keywords in this cluster
$keywords_response = $api->get("/planner/keywords/?cluster_id={$cluster_id}");
if ($keywords_response['success']) {
$keywords = $keywords_response['results'];
// Update each keyword status to 'mapped'
foreach ($keywords as $keyword) {
$api->put("/planner/keywords/{$keyword['id']}/", array(
'status' => 'mapped'
));
}
}
}
// Update task status to completed
$api->put("/writer/tasks/{$task_id}/", array(
'status' => 'completed',
'assigned_post_id' => $post_id,
'post_url' => get_permalink($post_id)
));
update_post_meta($post_id, '_igny8_last_synced', current_time('mysql'));
}
/**
* Sync post status changes to IGNY8
*
* @param string $new_status New post status
* @param string $old_status Old post status
* @param WP_Post $post Post object
*/
function igny8_sync_post_status_transition($new_status, $old_status, $post) {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return;
}
// Skip if status hasn't changed
if ($new_status === $old_status) {
return;
}
// Only sync IGNY8-managed posts
if (!igny8_is_igny8_managed_post($post->ID)) {
return;
}
$task_id = get_post_meta($post->ID, '_igny8_task_id', true);
if (!$task_id) {
return;
}
$api = new Igny8API();
// Map WordPress status to IGNY8 task status
$task_status = igny8_map_wp_status_to_igny8($new_status);
// Sync to IGNY8
$response = $api->put("/writer/tasks/{$task_id}/", array(
'status' => $task_status,
'assigned_post_id' => $post->ID,
'post_url' => get_permalink($post->ID)
));
if ($response['success']) {
update_post_meta($post->ID, '_igny8_last_synced', current_time('mysql'));
do_action('igny8_post_status_synced', $post->ID, $task_id, $new_status);
}
}
/**
* Batch sync all IGNY8-managed posts status to IGNY8 API
*
* @return array Sync results
*/
function igny8_batch_sync_post_statuses() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return array(
'synced' => 0,
'failed' => 0,
'total' => 0,
'disabled' => true
);
}
global $wpdb;
// Get all posts with IGNY8 task ID
$posts = $wpdb->get_results("
SELECT p.ID, p.post_status, p.post_title, pm.meta_value as task_id
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE pm.meta_key = '_igny8_task_id'
AND p.post_type IN ('post', 'page', 'product')
AND p.post_status != 'trash'
");
$api = new Igny8API();
$synced = 0;
$failed = 0;
foreach ($posts as $post_data) {
$post_id = $post_data->ID;
$task_id = intval($post_data->task_id);
$wp_status = $post_data->post_status;
// Map status
$task_status = igny8_map_wp_status_to_igny8($wp_status);
// Sync to IGNY8
$response = $api->put("/writer/tasks/{$task_id}/", array(
'status' => $task_status,
'assigned_post_id' => $post_id,
'post_url' => get_permalink($post_id)
));
if ($response['success']) {
update_post_meta($post_id, '_igny8_last_synced', current_time('mysql'));
$synced++;
} else {
$failed++;
error_log("IGNY8: Failed to sync post {$post_id}: " . ($response['error'] ?? 'Unknown error'));
}
}
return array(
'synced' => $synced,
'failed' => $failed,
'total' => count($posts)
);
}
/**
* Scheduled sync of WordPress post statuses to IGNY8
*/
function igny8_cron_sync_post_statuses() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
error_log('IGNY8: Connection disabled, skipping post status sync');
return;
}
$result = igny8_batch_sync_post_statuses();
error_log(sprintf(
'IGNY8: Synced %d posts, %d failed',
$result['synced'],
$result['failed']
));
}
/**
* Scheduled sync of site data
*/
function igny8_cron_sync_site_data() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
error_log('IGNY8: Connection disabled, skipping site data sync');
return;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
error_log('IGNY8: Site ID not set, skipping site data sync');
return;
}
if (function_exists('igny8_is_module_enabled') && !igny8_is_module_enabled('sites')) {
error_log('IGNY8: Sites module disabled, skipping incremental site sync');
return;
}
$settings = igny8_get_site_scan_settings(array(
'mode' => 'incremental',
'since' => get_option('igny8_last_site_sync', 0)
));
$result = igny8_sync_incremental_site_data($site_id, $settings);
if ($result) {
error_log(sprintf(
'IGNY8: Synced %d posts to site %d',
$result['synced'],
$site_id
));
} else {
error_log('IGNY8: Site data sync failed');
}
}
/**
* Scheduled full site scan (runs at most once per week)
*/
function igny8_cron_full_site_scan() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
return;
}
if (function_exists('igny8_is_module_enabled') && !igny8_is_module_enabled('sites')) {
return;
}
$last_full = intval(get_option('igny8_last_full_site_scan', 0));
if ($last_full && (time() - $last_full) < WEEK_IN_SECONDS) {
return;
}
$settings = igny8_get_site_scan_settings(array(
'mode' => 'full',
'since' => null
));
$result = igny8_perform_full_site_scan($site_id, $settings);
if ($result) {
error_log('IGNY8: Full site scan completed');
} else {
error_log('IGNY8: Full site scan failed');
}
}
/**
* Two-way sync class
*/
class Igny8WordPressSync {
/**
* API instance
*
* @var Igny8API
*/
private $api;
/**
* Constructor
*/
public function __construct() {
$this->api = new Igny8API();
// WordPress → IGNY8 hooks are registered in hooks.php
// IGNY8 → WordPress hooks can be added here if needed
}
}

View File

@@ -1,425 +0,0 @@
<?php
/**
* Taxonomy Synchronization
*
* Handles synchronization between WordPress taxonomies and IGNY8 sectors/clusters
*
* @package Igny8Bridge
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Sync WordPress taxonomy to IGNY8
*
* @param string $taxonomy Taxonomy name
* @return array|false Sync result or false on failure
*/
function igny8_sync_taxonomy_to_igny8($taxonomy) {
$api = new Igny8API();
if (!$api->is_authenticated()) {
return false;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
return false;
}
// Get taxonomy data
$taxonomy_obj = get_taxonomy($taxonomy);
if (!$taxonomy_obj) {
return false;
}
// Get all terms
$terms = get_terms(array(
'taxonomy' => $taxonomy,
'hide_empty' => false
));
if (is_wp_error($terms)) {
return false;
}
// Format taxonomy data
$taxonomy_data = array(
'name' => $taxonomy,
'label' => $taxonomy_obj->label,
'hierarchical' => $taxonomy_obj->hierarchical,
'terms' => array()
);
foreach ($terms as $term) {
$taxonomy_data['terms'][] = array(
'id' => $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
'description' => $term->description,
'parent' => $term->parent
);
}
// Send to IGNY8
$response = $api->post("/planner/sites/{$site_id}/taxonomies/", array(
'taxonomy' => $taxonomy_data
));
return $response['success'] ? $response['data'] : false;
}
/**
* Sync IGNY8 sectors to WordPress taxonomies
*
* @return array|false Sync result or false on failure
*/
function igny8_sync_igny8_sectors_to_wp() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return array('synced' => 0, 'total' => 0, 'skipped' => true, 'disabled' => true);
}
$api = new Igny8API();
if (!$api->is_authenticated()) {
return false;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
return false;
}
// Respect module toggle
$enabled_modules = function_exists('igny8_get_enabled_modules') ? igny8_get_enabled_modules() : array();
if (!in_array('planner', $enabled_modules, true)) {
return array('synced' => 0, 'total' => 0, 'skipped' => true);
}
// Get sectors from IGNY8
$response = $api->get("/planner/sites/{$site_id}/sectors/");
if (!$response['success']) {
return false;
}
$sectors = $response['data']['results'] ?? $response['data'] ?? $response['results'] ?? array();
$synced = 0;
foreach ($sectors as $sector) {
$term = term_exists($sector['name'], 'igny8_sectors');
if (!$term) {
$term = wp_insert_term(
$sector['name'],
'igny8_sectors',
array(
'description' => $sector['description'] ?? '',
'slug' => $sector['slug'] ?? sanitize_title($sector['name'])
)
);
} else {
wp_update_term($term['term_id'], 'igny8_sectors', array(
'description' => $sector['description'] ?? '',
'slug' => $sector['slug'] ?? sanitize_title($sector['name'])
));
}
if (!is_wp_error($term)) {
$term_id = is_array($term) ? $term['term_id'] : $term;
update_term_meta($term_id, '_igny8_sector_id', $sector['id']);
$synced++;
}
}
return array('synced' => $synced, 'total' => count($sectors));
}
/**
* Sync IGNY8 clusters to WordPress taxonomies
*
* @param int $sector_id Optional sector ID to filter clusters
* @return array|false Sync result or false on failure
*/
function igny8_sync_igny8_clusters_to_wp($sector_id = null) {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return array('synced' => 0, 'total' => 0, 'skipped' => true, 'disabled' => true);
}
$api = new Igny8API();
if (!$api->is_authenticated()) {
return false;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
return false;
}
$enabled_modules = function_exists('igny8_get_enabled_modules') ? igny8_get_enabled_modules() : array();
if (!in_array('planner', $enabled_modules, true)) {
return array('synced' => 0, 'total' => 0, 'skipped' => true);
}
// Build endpoint
$endpoint = "/planner/sites/{$site_id}/clusters/";
if ($sector_id) {
$endpoint .= "?sector_id={$sector_id}";
}
// Get clusters from IGNY8
$response = $api->get($endpoint);
if (!$response['success']) {
return false;
}
$clusters = $response['data']['results'] ?? $response['data'] ?? $response['results'] ?? array();
$synced = 0;
foreach ($clusters as $cluster) {
// Get parent sector term if sector_id exists
$parent = 0;
if (!empty($cluster['sector_id'])) {
$sector_terms = get_terms(array(
'taxonomy' => 'igny8_sectors',
'meta_key' => '_igny8_sector_id',
'meta_value' => $cluster['sector_id'],
'hide_empty' => false
));
if (!is_wp_error($sector_terms) && !empty($sector_terms)) {
$parent = $sector_terms[0]->term_id;
}
}
$term_id = 0;
$existing = get_terms(array(
'taxonomy' => 'igny8_clusters',
'meta_key' => '_igny8_cluster_id',
'meta_value' => $cluster['id'],
'hide_empty' => false
));
if (!is_wp_error($existing) && !empty($existing)) {
$term_id = $existing[0]->term_id;
}
if (!$term_id) {
$term = term_exists($cluster['name'], 'igny8_clusters');
} else {
$term = array('term_id' => $term_id);
}
if (!$term) {
$term = wp_insert_term(
$cluster['name'],
'igny8_clusters',
array(
'description' => $cluster['description'] ?? '',
'slug' => $cluster['slug'] ?? sanitize_title($cluster['name']),
'parent' => $parent
)
);
} else {
wp_update_term($term['term_id'], 'igny8_clusters', array(
'description' => $cluster['description'] ?? '',
'slug' => $cluster['slug'] ?? sanitize_title($cluster['name']),
'parent' => $parent
));
}
if (!is_wp_error($term)) {
$term_id = is_array($term) ? $term['term_id'] : $term;
update_term_meta($term_id, '_igny8_cluster_id', $cluster['id']);
if (!empty($cluster['sector_id'])) {
update_term_meta($term_id, '_igny8_sector_id', $cluster['sector_id']);
}
$synced++;
}
}
return array('synced' => $synced, 'total' => count($clusters));
}
/**
* Cron handler: sync sectors/clusters automatically
*
* @return array
*/
function igny8_cron_sync_taxonomies() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
error_log('IGNY8: Connection disabled, skipping taxonomy sync');
return array('sectors' => array('skipped' => true), 'clusters' => array('skipped' => true));
}
$results = array(
'sectors' => igny8_sync_igny8_sectors_to_wp(),
'clusters' => igny8_sync_igny8_clusters_to_wp()
);
update_option('igny8_last_taxonomy_sync', current_time('timestamp'));
return $results;
}
/**
* Sync planner keywords for all referenced clusters
*
* @return array|false
*/
function igny8_sync_keywords_from_planner() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
return array('synced_clusters' => 0, 'synced_posts' => 0, 'skipped' => true, 'disabled' => true);
}
$api = new Igny8API();
if (!$api->is_authenticated()) {
return false;
}
$site_id = get_option('igny8_site_id');
if (!$site_id) {
return false;
}
$enabled_modules = function_exists('igny8_get_enabled_modules') ? igny8_get_enabled_modules() : array();
if (!in_array('planner', $enabled_modules, true)) {
return array('synced_clusters' => 0, 'synced_posts' => 0, 'skipped' => true);
}
global $wpdb;
$cluster_ids = $wpdb->get_col("
SELECT DISTINCT meta_value
FROM {$wpdb->postmeta}
WHERE meta_key = '_igny8_cluster_id'
AND meta_value IS NOT NULL
AND meta_value != ''
");
if (empty($cluster_ids)) {
return array('synced_clusters' => 0, 'synced_posts' => 0);
}
$enabled_post_types = function_exists('igny8_get_enabled_post_types') ? igny8_get_enabled_post_types() : array('post', 'page');
$synced_clusters = 0;
$synced_posts = 0;
foreach ($cluster_ids as $cluster_id) {
$cluster_id = intval($cluster_id);
if (!$cluster_id) {
continue;
}
$response = $api->get("/planner/keywords/?cluster_id={$cluster_id}&page_size=500");
if (!$response['success']) {
continue;
}
$keywords = $response['data']['results'] ?? $response['data'] ?? $response['results'] ?? array();
$keyword_ids = array_map('intval', wp_list_pluck($keywords, 'id'));
// Update cluster term meta
$cluster_terms = get_terms(array(
'taxonomy' => 'igny8_clusters',
'meta_key' => '_igny8_cluster_id',
'meta_value' => $cluster_id,
'hide_empty' => false
));
if (!is_wp_error($cluster_terms) && !empty($cluster_terms)) {
foreach ($cluster_terms as $term) {
update_term_meta($term->term_id, '_igny8_keyword_ids', $keyword_ids);
}
}
// Update posts tied to this cluster
$posts = get_posts(array(
'post_type' => $enabled_post_types,
'meta_query' => array(
array(
'key' => '_igny8_cluster_id',
'value' => $cluster_id,
'compare' => '='
)
),
'post_status' => 'any',
'fields' => 'ids',
'nopaging' => true
));
foreach ($posts as $post_id) {
update_post_meta($post_id, '_igny8_keyword_ids', $keyword_ids);
$synced_posts++;
}
$synced_clusters++;
}
return array(
'synced_clusters' => $synced_clusters,
'synced_posts' => $synced_posts
);
}
/**
* Cron handler: sync planner keywords
*
* @return array|false
*/
function igny8_cron_sync_keywords() {
// Skip if connection is disabled
if (!igny8_is_connection_enabled()) {
error_log('IGNY8: Connection disabled, skipping keyword sync');
return array('synced_clusters' => 0, 'synced_posts' => 0, 'skipped' => true);
}
$result = igny8_sync_keywords_from_planner();
if ($result !== false) {
update_option('igny8_last_keyword_sync', current_time('timestamp'));
}
return $result;
}
/**
* Map WordPress taxonomy term to IGNY8 cluster
*
* @param int $term_id Term ID
* @param string $taxonomy Taxonomy name
* @param int $cluster_id IGNY8 cluster ID
* @return bool True on success
*/
function igny8_map_term_to_cluster($term_id, $taxonomy, $cluster_id) {
if ($taxonomy !== 'igny8_clusters') {
return false;
}
update_term_meta($term_id, '_igny8_cluster_id', $cluster_id);
return true;
}
/**
* Map WordPress taxonomy to IGNY8 sector
*
* @param string $taxonomy Taxonomy name
* @param int $sector_id IGNY8 sector ID
* @return bool True on success
*/
function igny8_map_taxonomy_to_sector($taxonomy, $sector_id) {
// Store mapping in options
$mappings = get_option('igny8_taxonomy_sector_mappings', array());
$mappings[$taxonomy] = $sector_id;
update_option('igny8_taxonomy_sector_mappings', $mappings);
return true;
}