reference plugin and image gen analysis
This commit is contained in:
485
igny8-ai-seo-wp-plugin/flows/sync-ajax.php
Normal file
485
igny8-ai-seo-wp-plugin/flows/sync-ajax.php
Normal file
@@ -0,0 +1,485 @@
|
||||
<?php
|
||||
/**
|
||||
* ==========================
|
||||
* 🔐 IGNY8 FILE RULE HEADER
|
||||
* ==========================
|
||||
* @file : sync-ajax.php
|
||||
* @location : /flows/sync-ajax.php
|
||||
* @type : AJAX Handler
|
||||
* @scope : Global
|
||||
* @allowed : AJAX endpoints, automation handlers, workflow operations
|
||||
* @reusability : Globally Reusable
|
||||
* @notes : Automation-specific AJAX handlers for all workflows
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook handlers for cluster metrics updates
|
||||
*/
|
||||
|
||||
// Hook for when keywords are added
|
||||
// Hook definitions moved to sync-hooks.php
|
||||
|
||||
|
||||
/**
|
||||
* Handle keyword cluster updates
|
||||
*/
|
||||
function igny8_handle_keyword_cluster_update($record_id, $cluster_id) {
|
||||
if ($cluster_id) {
|
||||
try {
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
} catch (Exception $e) {
|
||||
error_log("ERROR in igny8_handle_keyword_cluster_update: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AJAX handler for keyword imports with workflow automation
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_ajax_import_keywords() {
|
||||
// Verify nonce
|
||||
if (!wp_verify_nonce($_POST['nonce'], 'igny8_ajax_nonce')) {
|
||||
wp_send_json_error('Security check failed');
|
||||
}
|
||||
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Insufficient permissions');
|
||||
}
|
||||
|
||||
$keywords_data = $_POST['keywords'] ?? [];
|
||||
|
||||
if (empty($keywords_data) || !is_array($keywords_data)) {
|
||||
wp_send_json_error('No keywords data provided');
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$imported_ids = [];
|
||||
|
||||
try {
|
||||
// Import keywords
|
||||
foreach ($keywords_data as $keyword_data) {
|
||||
$sanitized_data = [
|
||||
'keyword' => sanitize_text_field($keyword_data['keyword'] ?? ''),
|
||||
'search_volume' => intval($keyword_data['search_volume'] ?? 0),
|
||||
'difficulty' => sanitize_text_field($keyword_data['difficulty'] ?? ''),
|
||||
'cpc' => floatval($keyword_data['cpc'] ?? 0),
|
||||
'intent' => sanitize_text_field($keyword_data['intent'] ?? ''),
|
||||
'status' => 'unmapped',
|
||||
'created_at' => current_time('mysql'),
|
||||
'updated_at' => current_time('mysql')
|
||||
];
|
||||
|
||||
// Skip empty keywords
|
||||
if (empty($sanitized_data['keyword'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $wpdb->insert(
|
||||
$wpdb->prefix . 'igny8_keywords',
|
||||
$sanitized_data,
|
||||
['%s', '%d', '%s', '%f', '%s', '%s', '%s', '%s']
|
||||
);
|
||||
|
||||
if ($result !== false) {
|
||||
$imported_ids[] = $wpdb->insert_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($imported_ids)) {
|
||||
wp_send_json_error('No keywords were imported');
|
||||
}
|
||||
|
||||
// Trigger workflow automation for imported keywords
|
||||
$workflow_result = igny8_workflow_triggers('keywords_imported', ['keyword_ids' => $imported_ids]);
|
||||
|
||||
// Prepare response
|
||||
$response = [
|
||||
'message' => 'Keywords imported successfully',
|
||||
'imported_count' => count($imported_ids),
|
||||
'keyword_ids' => $imported_ids
|
||||
];
|
||||
|
||||
if ($workflow_result && $workflow_result['success']) {
|
||||
$response['workflow_message'] = $workflow_result['message'];
|
||||
if (isset($workflow_result['clusters_created'])) {
|
||||
$response['workflow_data'] = [
|
||||
'clusters_created' => $workflow_result['clusters_created'],
|
||||
'cluster_ids' => $workflow_result['cluster_ids'] ?? []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success($response);
|
||||
|
||||
} catch (Exception $e) {
|
||||
wp_send_json_error('Import error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for creating a single task from an idea
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_create_task_from_idea_ajax() {
|
||||
try {
|
||||
check_ajax_referer('igny8_ajax_nonce', 'nonce');
|
||||
if (!current_user_can('edit_posts')) {
|
||||
wp_send_json_error(['message' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
$idea_id = isset($_POST['idea_id']) ? absint($_POST['idea_id']) : 0;
|
||||
if (!$idea_id) {
|
||||
wp_send_json_error(['message' => 'Invalid idea id']);
|
||||
}
|
||||
|
||||
$result = igny8_create_task_from_idea($idea_id);
|
||||
wp_send_json($result);
|
||||
} catch (Exception $e) {
|
||||
wp_send_json_error(['message' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for bulk creating tasks from ideas
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_bulk_create_tasks_from_ideas_ajax() {
|
||||
try {
|
||||
check_ajax_referer('igny8_ajax_nonce', 'nonce');
|
||||
if (!current_user_can('edit_posts')) {
|
||||
wp_send_json_error(['message' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
$ids = isset($_POST['idea_ids']) ? array_map('absint', (array)$_POST['idea_ids']) : [];
|
||||
$ids = array_values(array_filter($ids));
|
||||
if (empty($ids)) {
|
||||
wp_send_json_error(['message' => 'No idea ids provided']);
|
||||
}
|
||||
|
||||
// Check if ideas have status other than 'new'
|
||||
global $wpdb;
|
||||
$placeholders = implode(',', array_fill(0, count($ids), '%d'));
|
||||
$ideas_status = $wpdb->get_results($wpdb->prepare("
|
||||
SELECT id, idea_title, status FROM {$wpdb->prefix}igny8_content_ideas
|
||||
WHERE id IN ({$placeholders}) AND status != 'new'
|
||||
", $ids));
|
||||
|
||||
if (!empty($ideas_status)) {
|
||||
$idea_titles = array_column($ideas_status, 'idea_title');
|
||||
wp_send_json_error(['message' => 'Ideas are not in "new" status: ' . implode(', ', array_slice($idea_titles, 0, 3)) . (count($idea_titles) > 3 ? '...' : '')]);
|
||||
}
|
||||
|
||||
$created = [];
|
||||
$skipped = [];
|
||||
$failed = [];
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$res = igny8_create_task_from_idea($id);
|
||||
if (!empty($res['success'])) {
|
||||
if (!empty($res['task_id'])) {
|
||||
$created[] = $res['task_id'];
|
||||
} else {
|
||||
$skipped[] = $id;
|
||||
}
|
||||
} else {
|
||||
$failed[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
// Update metrics once per unique idea id to be safe
|
||||
foreach ($ids as $id) {
|
||||
igny8_update_idea_metrics($id);
|
||||
}
|
||||
|
||||
wp_send_json_success([
|
||||
'created' => $created,
|
||||
'skipped' => $skipped,
|
||||
'failed' => $failed,
|
||||
'message' => sprintf('Created %d, skipped %d, failed %d', count($created), count($skipped), count($failed))
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
wp_send_json_error(['message' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a task from an idea
|
||||
*
|
||||
* @param int $idea_id The idea ID to create task from
|
||||
* @return array Result array with success status and message
|
||||
*/
|
||||
function igny8_create_task_from_idea($idea_id) {
|
||||
global $wpdb;
|
||||
|
||||
$idea = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT id, idea_title, idea_description, content_structure, content_type, keyword_cluster_id, estimated_word_count, target_keywords
|
||||
FROM {$wpdb->prefix}igny8_content_ideas WHERE id=%d",
|
||||
$idea_id
|
||||
));
|
||||
|
||||
if (!$idea) {
|
||||
return ['success' => false, 'message' => 'Idea not found'];
|
||||
}
|
||||
|
||||
// Optional dedupe policy: One open task per idea
|
||||
$existing = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT id FROM {$wpdb->prefix}igny8_tasks WHERE idea_id=%d AND status IN ('draft','queued','in_progress','review') LIMIT 1",
|
||||
$idea_id
|
||||
));
|
||||
|
||||
if ($existing) {
|
||||
return ['success' => true, 'message' => 'Task already exists for this idea', 'task_id' => (int)$existing];
|
||||
}
|
||||
|
||||
$ins = $wpdb->insert($wpdb->prefix . 'igny8_tasks', [
|
||||
'title' => $idea->idea_title,
|
||||
'description' => $idea->idea_description,
|
||||
'content_structure' => $idea->content_structure ?: 'cluster_hub',
|
||||
'content_type' => $idea->content_type ?: 'post',
|
||||
'cluster_id' => $idea->keyword_cluster_id ?: null,
|
||||
'priority' => 'medium',
|
||||
'status' => 'queued',
|
||||
'idea_id' => (int)$idea_id,
|
||||
'keywords' => $idea->target_keywords ?: '',
|
||||
'word_count' => $idea->estimated_word_count ?: 0,
|
||||
'schedule_at' => null,
|
||||
'assigned_post_id' => null,
|
||||
'created_at' => current_time('mysql'),
|
||||
'updated_at' => current_time('mysql')
|
||||
], ['%s', '%s', '%s', '%s', '%d', '%s', '%s', '%d', '%s', '%d', '%s', '%d', '%s', '%s']);
|
||||
|
||||
if ($ins === false) {
|
||||
return ['success' => false, 'message' => 'Failed to create task'];
|
||||
}
|
||||
|
||||
$task_id = (int)$wpdb->insert_id;
|
||||
|
||||
// Update idea status to 'scheduled' when successfully queued to writer
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'igny8_content_ideas',
|
||||
['status' => 'scheduled'],
|
||||
['id' => $idea_id],
|
||||
['%s'],
|
||||
['%d']
|
||||
);
|
||||
|
||||
// Update keyword status to 'queued' when task is created from idea
|
||||
if ($idea->keyword_cluster_id) {
|
||||
// Get all keywords in this cluster and update their status to 'queued'
|
||||
$keyword_ids = $wpdb->get_col($wpdb->prepare("
|
||||
SELECT id FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE cluster_id = %d
|
||||
", $idea->keyword_cluster_id));
|
||||
|
||||
if (!empty($keyword_ids)) {
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$wpdb->query($wpdb->prepare("
|
||||
UPDATE {$wpdb->prefix}igny8_keywords
|
||||
SET status = 'queued'
|
||||
WHERE id IN ({$placeholders})
|
||||
", $keyword_ids));
|
||||
}
|
||||
}
|
||||
|
||||
igny8_update_idea_metrics($idea_id);
|
||||
igny8_write_log('queue_to_writer', ['idea_id' => $idea_id, 'task_id' => $task_id]);
|
||||
|
||||
return ['success' => true, 'message' => "Task queued for Writer", "task_id" => $task_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for bulk deleting keywords
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_ajax_bulk_delete_keywords() {
|
||||
// Verify nonce for security
|
||||
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce', true)) {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
}
|
||||
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(['message' => 'You do not have permission to perform this action.']);
|
||||
}
|
||||
|
||||
// Get parameters
|
||||
$keyword_ids = $_POST['keyword_ids'] ?? [];
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
wp_send_json_error(['message' => 'No keywords selected for deletion.']);
|
||||
}
|
||||
|
||||
// Call bulk delete function
|
||||
$result = igny8_bulk_delete_keywords($keyword_ids);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success([
|
||||
'message' => $result['message'],
|
||||
'deleted_count' => $result['deleted_count']
|
||||
]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => $result['message']]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for bulk mapping keywords to cluster
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_ajax_bulk_map_keywords() {
|
||||
// Verify nonce for security
|
||||
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce', true)) {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
}
|
||||
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(['message' => 'You do not have permission to perform this action.']);
|
||||
}
|
||||
|
||||
// Get parameters
|
||||
$keyword_ids = $_POST['keyword_ids'] ?? [];
|
||||
$cluster_id = intval($_POST['cluster_id'] ?? 0);
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
wp_send_json_error(['message' => 'No keywords selected for mapping.']);
|
||||
}
|
||||
|
||||
if (empty($cluster_id)) {
|
||||
wp_send_json_error(['message' => 'No cluster selected for mapping.']);
|
||||
}
|
||||
|
||||
// Call bulk map function
|
||||
$result = igny8_bulk_map_keywords($keyword_ids, $cluster_id);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success([
|
||||
'message' => $result['message'],
|
||||
'mapped_count' => $result['mapped_count']
|
||||
]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => $result['message']]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for bulk unmapping keywords from clusters
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_ajax_bulk_unmap_keywords() {
|
||||
// Verify nonce for security
|
||||
if (!check_ajax_referer('igny8_ajax_nonce', 'nonce', true)) {
|
||||
wp_send_json_error(['message' => 'Security check failed.']);
|
||||
}
|
||||
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error(['message' => 'You do not have permission to perform this action.']);
|
||||
}
|
||||
|
||||
// Get parameters
|
||||
$keyword_ids = $_POST['keyword_ids'] ?? [];
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
wp_send_json_error(['message' => 'No keywords selected for unmapping.']);
|
||||
}
|
||||
|
||||
// Call bulk unmap function
|
||||
$result = igny8_bulk_unmap_keywords($keyword_ids);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success([
|
||||
'message' => $result['message'],
|
||||
'unmapped_count' => $result['unmapped_count']
|
||||
]);
|
||||
} else {
|
||||
wp_send_json_error(['message' => $result['message']]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for bulk deleting records
|
||||
*/
|
||||
// Hook moved to sync-hooks.php
|
||||
function igny8_delete_bulk_records() {
|
||||
// Verify nonce
|
||||
if (!wp_verify_nonce($_POST['nonce'], 'igny8_ajax_nonce')) {
|
||||
wp_send_json_error('Security check failed');
|
||||
}
|
||||
|
||||
// Check user capabilities
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Insufficient permissions');
|
||||
}
|
||||
|
||||
// Get parameters
|
||||
$table_id = sanitize_text_field($_POST['table_id'] ?? '');
|
||||
$record_ids = $_POST['record_ids'] ?? [];
|
||||
|
||||
if (empty($table_id) || empty($record_ids) || !is_array($record_ids)) {
|
||||
wp_send_json_error('Table ID and Record IDs required');
|
||||
}
|
||||
|
||||
// Get table name
|
||||
$table_name = igny8_get_table_name($table_id);
|
||||
if (!$table_name) {
|
||||
wp_send_json_error('Invalid table ID');
|
||||
}
|
||||
|
||||
// Sanitize IDs
|
||||
$record_ids = array_map('intval', $record_ids);
|
||||
$record_ids = array_filter($record_ids, function($id) { return $id > 0; });
|
||||
|
||||
if (empty($record_ids)) {
|
||||
wp_send_json_error('No valid record IDs provided');
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Handle cluster deletion - clean up keyword relationships
|
||||
if ($table_id === 'planner_clusters') {
|
||||
// Before deleting clusters, unmap all keywords from these clusters
|
||||
$placeholders = implode(',', array_fill(0, count($record_ids), '%d'));
|
||||
$unmapped_count = $wpdb->query($wpdb->prepare(
|
||||
"UPDATE {$wpdb->prefix}igny8_keywords
|
||||
SET cluster_id = NULL, status = 'unmapped', updated_at = CURRENT_TIMESTAMP
|
||||
WHERE cluster_id IN ({$placeholders})",
|
||||
$record_ids
|
||||
));
|
||||
|
||||
if ($unmapped_count !== false) {
|
||||
// Log the unmapping
|
||||
error_log("Igny8: Unmapped {$unmapped_count} keywords from deleted clusters: " . implode(',', $record_ids));
|
||||
}
|
||||
}
|
||||
|
||||
// Build placeholders for IN clause
|
||||
$placeholders = implode(',', array_fill(0, count($record_ids), '%d'));
|
||||
|
||||
try {
|
||||
$result = $wpdb->query($wpdb->prepare(
|
||||
"DELETE FROM `{$table_name}` WHERE id IN ({$placeholders})",
|
||||
$record_ids
|
||||
));
|
||||
|
||||
if ($result === false) {
|
||||
wp_send_json_error('Failed to delete records');
|
||||
}
|
||||
|
||||
wp_send_json_success([
|
||||
'message' => "Successfully deleted {$result} record(s)",
|
||||
'deleted_count' => $result
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
wp_send_json_error('Database error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
673
igny8-ai-seo-wp-plugin/flows/sync-functions.php
Normal file
673
igny8-ai-seo-wp-plugin/flows/sync-functions.php
Normal file
@@ -0,0 +1,673 @@
|
||||
<?php
|
||||
/**
|
||||
* ==========================
|
||||
* 🔐 IGNY8 FILE RULE HEADER
|
||||
* ==========================
|
||||
* @file : sync-functions.php
|
||||
* @location : /flows/sync-functions.php
|
||||
* @type : Function Library
|
||||
* @scope : Global
|
||||
* @allowed : Automation logic, workflow functions, sync operations
|
||||
* @reusability : Globally Reusable
|
||||
* @notes : Core automation functions for all workflows
|
||||
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update cluster metrics based on related keywords and mappings
|
||||
*/
|
||||
function igny8_update_cluster_metrics($cluster_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$cluster_id) {
|
||||
return ['success' => false, 'message' => 'Operation failed'];
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Get keyword count and aggregated data
|
||||
$keyword_data = $wpdb->get_row($wpdb->prepare("
|
||||
SELECT
|
||||
COUNT(*) as keyword_count,
|
||||
COALESCE(SUM(search_volume), 0) as total_volume,
|
||||
COALESCE(AVG(difficulty), 0) as avg_difficulty
|
||||
FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE cluster_id = %d
|
||||
", $cluster_id));
|
||||
|
||||
// Get mapped pages count from taxonomy relationships
|
||||
$cluster_term_id = $wpdb->get_var($wpdb->prepare("
|
||||
SELECT cluster_term_id FROM {$wpdb->prefix}igny8_clusters WHERE id = %d
|
||||
", $cluster_id));
|
||||
|
||||
$mapped_pages_count = 0;
|
||||
if ($cluster_term_id) {
|
||||
// Count content (posts, pages, products) associated with this cluster term
|
||||
$mapped_pages_count = $wpdb->get_var($wpdb->prepare("
|
||||
SELECT COUNT(DISTINCT object_id)
|
||||
FROM {$wpdb->prefix}term_relationships tr
|
||||
INNER JOIN {$wpdb->prefix}term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
||||
WHERE tt.term_id = %d AND tt.taxonomy = 'clusters'
|
||||
", $cluster_term_id));
|
||||
}
|
||||
|
||||
// Update cluster record
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'igny8_clusters',
|
||||
[
|
||||
'keyword_count' => intval($keyword_data->keyword_count),
|
||||
'total_volume' => intval($keyword_data->total_volume),
|
||||
'avg_difficulty' => floatval($keyword_data->avg_difficulty),
|
||||
'mapped_pages_count' => intval($mapped_pages_count)
|
||||
],
|
||||
['id' => $cluster_id],
|
||||
['%d', '%d', '%f', '%d'],
|
||||
['%d']
|
||||
);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("ERROR in igny8_update_cluster_metrics: " . $e->getMessage());
|
||||
return ['success' => false, 'message' => 'Failed to update cluster metrics: ' . $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update campaign metrics
|
||||
*/
|
||||
function igny8_update_campaign_metrics($campaign_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$campaign_id) {
|
||||
return ['success' => false, 'message' => 'Operation failed'];
|
||||
}
|
||||
|
||||
// Get campaign performance data
|
||||
$performance_data = $wpdb->get_row($wpdb->prepare("
|
||||
SELECT
|
||||
COUNT(*) as total_tasks,
|
||||
COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_tasks,
|
||||
COALESCE(AVG(seo_score), 0) as avg_seo_score
|
||||
FROM {$wpdb->prefix}igny8_tasks
|
||||
WHERE campaign_id = %d
|
||||
", $campaign_id));
|
||||
|
||||
// Update campaign record
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'igny8_campaigns',
|
||||
[
|
||||
'total_tasks' => intval($performance_data->total_tasks),
|
||||
'completed_tasks' => intval($performance_data->completed_tasks),
|
||||
'avg_seo_score' => floatval($performance_data->avg_seo_score)
|
||||
],
|
||||
['id' => $campaign_id],
|
||||
['%d', '%d', '%f'],
|
||||
['%d']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update idea metrics based on related tasks
|
||||
*/
|
||||
function igny8_update_idea_metrics($idea_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$idea_id) {
|
||||
return ['success' => false, 'message' => 'Operation failed'];
|
||||
}
|
||||
|
||||
// Get tasks count for this idea
|
||||
$tasks_count = $wpdb->get_var($wpdb->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM {$wpdb->prefix}igny8_tasks
|
||||
WHERE idea_id = %d
|
||||
", $idea_id));
|
||||
|
||||
// Update idea record
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'igny8_content_ideas',
|
||||
[
|
||||
'tasks_count' => intval($tasks_count)
|
||||
],
|
||||
['id' => $idea_id],
|
||||
['%d'],
|
||||
['%d']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update task metrics based on related variations
|
||||
*/
|
||||
// REMOVED: Task variations functionality - tasks don't need variations
|
||||
|
||||
/**
|
||||
* Update keyword status when WordPress post is published
|
||||
*
|
||||
* @param int $post_id The WordPress post ID that was published
|
||||
*/
|
||||
function igny8_update_keywords_on_post_publish($post_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$post_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find tasks that are assigned to this post
|
||||
$tasks = $wpdb->get_results($wpdb->prepare("
|
||||
SELECT id, cluster_id
|
||||
FROM {$wpdb->prefix}igny8_tasks
|
||||
WHERE assigned_post_id = %d AND cluster_id IS NOT NULL
|
||||
", $post_id));
|
||||
|
||||
if (empty($tasks)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update keyword status to 'mapped' for all keywords in the clusters of published tasks
|
||||
foreach ($tasks as $task) {
|
||||
if ($task->cluster_id) {
|
||||
// Get all keywords in this cluster and update their status to 'mapped'
|
||||
$keyword_ids = $wpdb->get_col($wpdb->prepare("
|
||||
SELECT id FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE cluster_id = %d
|
||||
", $task->cluster_id));
|
||||
|
||||
if (!empty($keyword_ids)) {
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$wpdb->query($wpdb->prepare("
|
||||
UPDATE {$wpdb->prefix}igny8_keywords
|
||||
SET status = 'mapped'
|
||||
WHERE id IN ({$placeholders})
|
||||
", $keyword_ids));
|
||||
}
|
||||
|
||||
// Update task status to 'completed'
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'igny8_tasks',
|
||||
['status' => 'completed'],
|
||||
['id' => $task->id],
|
||||
['%s'],
|
||||
['%d']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Log the event
|
||||
if (function_exists('igny8_write_log')) {
|
||||
igny8_write_log('post_published', [
|
||||
'post_id' => $post_id,
|
||||
'tasks_updated' => count($tasks),
|
||||
'message' => 'Keywords updated to mapped status'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically create clusters from keywords using AI clustering
|
||||
*
|
||||
* @param array $keyword_ids Optional array of keyword IDs to cluster. If empty, uses all unmapped keywords.
|
||||
* @return array Result array with success status and message
|
||||
*/
|
||||
function igny8_auto_create_clusters_from_keywords($keyword_ids = []) {
|
||||
global $wpdb;
|
||||
|
||||
// If no keyword IDs provided, get all unmapped keywords
|
||||
if (empty($keyword_ids)) {
|
||||
$keyword_ids = $wpdb->get_col("
|
||||
SELECT id FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE cluster_id IS NULL
|
||||
");
|
||||
}
|
||||
|
||||
if (empty($keyword_ids)) {
|
||||
return ['success' => true, 'message' => 'No unmapped keywords found for clustering'];
|
||||
}
|
||||
|
||||
// Limit to 20 keywords for AI processing
|
||||
if (count($keyword_ids) > 20) {
|
||||
$keyword_ids = array_slice($keyword_ids, 0, 20);
|
||||
}
|
||||
|
||||
// Get keywords data
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$keywords = $wpdb->get_results($wpdb->prepare("
|
||||
SELECT * FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE id IN ({$placeholders})
|
||||
", $keyword_ids));
|
||||
|
||||
if (empty($keywords)) {
|
||||
return ['success' => false, 'message' => 'No valid keywords found for clustering'];
|
||||
}
|
||||
|
||||
// Create clusters using AI (this would call the AI clustering function)
|
||||
// For now, create a simple cluster with all keywords
|
||||
$cluster_name = igny8_generate_cluster_name_from_keywords(array_column($keywords, 'keyword'));
|
||||
|
||||
// Create cluster
|
||||
$cluster_result = $wpdb->insert(
|
||||
$wpdb->prefix . 'igny8_clusters',
|
||||
[
|
||||
'cluster_name' => $cluster_name,
|
||||
'status' => 'active',
|
||||
'created_at' => current_time('mysql')
|
||||
],
|
||||
['%s', '%s', '%s']
|
||||
);
|
||||
|
||||
if ($cluster_result === false) {
|
||||
return ['success' => false, 'message' => 'Failed to create cluster'];
|
||||
}
|
||||
|
||||
$cluster_id = $wpdb->insert_id;
|
||||
|
||||
// Trigger cluster_added action to create taxonomy term
|
||||
do_action('igny8_cluster_added', $cluster_id);
|
||||
|
||||
// Map all keywords to this cluster
|
||||
$mapped_count = $wpdb->query($wpdb->prepare("
|
||||
UPDATE {$wpdb->prefix}igny8_keywords
|
||||
SET cluster_id = %d, status = 'mapped'
|
||||
WHERE id IN ({$placeholders})
|
||||
", array_merge([$cluster_id], $keyword_ids)));
|
||||
|
||||
// Update cluster metrics
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => "Created cluster '{$cluster_name}' with {$mapped_count} keywords",
|
||||
'cluster_id' => $cluster_id,
|
||||
'mapped_count' => $mapped_count
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Workflow automation trigger system
|
||||
*/
|
||||
function igny8_workflow_triggers($event, $payload = []) {
|
||||
switch ($event) {
|
||||
case 'keywords_imported':
|
||||
if (isset($payload['keyword_ids'])) {
|
||||
return igny8_auto_create_clusters_from_keywords($payload['keyword_ids']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'cluster_created':
|
||||
if (isset($payload['cluster_id'])) {
|
||||
// Create ideas from cluster
|
||||
$ideas_result = igny8_auto_create_ideas_from_clusters($payload['cluster_id']);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Cluster workflow completed',
|
||||
'ideas' => $ideas_result
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return ['success' => true, 'message' => 'No workflow automation for this event'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bulk delete keywords with cluster metrics update
|
||||
*/
|
||||
function igny8_bulk_delete_keywords($keyword_ids) {
|
||||
global $wpdb;
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
return ['success' => false, 'message' => 'Operation failed'];
|
||||
}
|
||||
|
||||
// Get cluster IDs before deletion for metrics update
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$cluster_ids = $wpdb->get_col($wpdb->prepare("
|
||||
SELECT DISTINCT cluster_id
|
||||
FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE id IN ({$placeholders})
|
||||
AND cluster_id IS NOT NULL
|
||||
", $keyword_ids));
|
||||
|
||||
// Delete keywords
|
||||
$result = $wpdb->query($wpdb->prepare("
|
||||
DELETE FROM {$wpdb->prefix}igny8_keywords
|
||||
WHERE id IN ({$placeholders})
|
||||
", $keyword_ids));
|
||||
|
||||
if ($result !== false) {
|
||||
// Update cluster metrics for affected clusters
|
||||
foreach ($cluster_ids as $cluster_id) {
|
||||
if ($cluster_id) {
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return ['success' => false, 'message' => 'Operation failed'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk map keywords to cluster
|
||||
*
|
||||
* @param array $keyword_ids Array of keyword IDs to map
|
||||
* @param int $cluster_id Cluster ID to map keywords to
|
||||
* @return array ['success' => bool, 'message' => string, 'mapped_count' => int]
|
||||
*/
|
||||
function igny8_bulk_map_keywords($keyword_ids, $cluster_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
return ['success' => false, 'message' => 'No keywords selected for mapping', 'mapped_count' => 0];
|
||||
}
|
||||
|
||||
if (empty($cluster_id) || !is_numeric($cluster_id)) {
|
||||
return ['success' => false, 'message' => 'Invalid cluster ID provided', 'mapped_count' => 0];
|
||||
}
|
||||
|
||||
$cluster_id = intval($cluster_id);
|
||||
|
||||
// Verify cluster exists
|
||||
$cluster_exists = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$wpdb->prefix}igny8_clusters WHERE id = %d",
|
||||
$cluster_id
|
||||
));
|
||||
|
||||
if (!$cluster_exists) {
|
||||
return ['success' => false, 'message' => 'Cluster not found', 'mapped_count' => 0];
|
||||
}
|
||||
|
||||
// Sanitize and validate IDs
|
||||
$keyword_ids = array_map('intval', $keyword_ids);
|
||||
$keyword_ids = array_filter($keyword_ids, function($id) { return $id > 0; });
|
||||
|
||||
if (empty($keyword_ids)) {
|
||||
return ['success' => false, 'message' => 'No valid keyword IDs provided', 'mapped_count' => 0];
|
||||
}
|
||||
|
||||
// Get old cluster IDs for metrics update
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$old_cluster_ids = $wpdb->get_col($wpdb->prepare(
|
||||
"SELECT DISTINCT cluster_id FROM {$wpdb->prefix}igny8_keywords WHERE id IN ({$placeholders}) AND cluster_id IS NOT NULL",
|
||||
$keyword_ids
|
||||
));
|
||||
|
||||
// Update keywords to new cluster
|
||||
$mapped_count = $wpdb->query($wpdb->prepare(
|
||||
"UPDATE {$wpdb->prefix}igny8_keywords SET cluster_id = %d, status = 'mapped', updated_at = CURRENT_TIMESTAMP WHERE id IN ({$placeholders})",
|
||||
array_merge([$cluster_id], $keyword_ids)
|
||||
));
|
||||
|
||||
if ($mapped_count === false) {
|
||||
return ['success' => false, 'message' => 'Failed to map keywords to cluster', 'mapped_count' => 0];
|
||||
}
|
||||
|
||||
// Update metrics for old clusters (they lost keywords)
|
||||
if (!empty($old_cluster_ids)) {
|
||||
foreach (array_unique($old_cluster_ids) as $old_cluster_id) {
|
||||
if ($old_cluster_id && $old_cluster_id != $cluster_id) {
|
||||
igny8_update_cluster_metrics($old_cluster_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update metrics for new cluster (gained keywords)
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => "Successfully mapped {$mapped_count} keyword(s) to cluster",
|
||||
'mapped_count' => $mapped_count
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk unmap keywords from their clusters
|
||||
*
|
||||
* @param array $keyword_ids Array of keyword IDs to unmap
|
||||
* @return array ['success' => bool, 'message' => string, 'unmapped_count' => int]
|
||||
*/
|
||||
function igny8_bulk_unmap_keywords($keyword_ids) {
|
||||
global $wpdb;
|
||||
|
||||
if (empty($keyword_ids) || !is_array($keyword_ids)) {
|
||||
return ['success' => false, 'message' => 'No keywords selected for unmapping', 'unmapped_count' => 0];
|
||||
}
|
||||
|
||||
// Sanitize and validate IDs
|
||||
$keyword_ids = array_map('intval', $keyword_ids);
|
||||
$keyword_ids = array_filter($keyword_ids, function($id) { return $id > 0; });
|
||||
|
||||
if (empty($keyword_ids)) {
|
||||
return ['success' => false, 'message' => 'No valid keyword IDs provided', 'unmapped_count' => 0];
|
||||
}
|
||||
|
||||
// Get cluster IDs before unmapping for metrics update
|
||||
$placeholders = implode(',', array_fill(0, count($keyword_ids), '%d'));
|
||||
$cluster_ids = $wpdb->get_col($wpdb->prepare(
|
||||
"SELECT DISTINCT cluster_id FROM {$wpdb->prefix}igny8_keywords WHERE id IN ({$placeholders}) AND cluster_id IS NOT NULL",
|
||||
$keyword_ids
|
||||
));
|
||||
|
||||
// Update keywords to unmap them
|
||||
$unmapped_count = $wpdb->query($wpdb->prepare(
|
||||
"UPDATE {$wpdb->prefix}igny8_keywords SET cluster_id = NULL, status = 'unmapped', updated_at = CURRENT_TIMESTAMP WHERE id IN ({$placeholders})",
|
||||
$keyword_ids
|
||||
));
|
||||
|
||||
if ($unmapped_count === false) {
|
||||
return ['success' => false, 'message' => 'Failed to unmap keywords from clusters', 'unmapped_count' => 0];
|
||||
}
|
||||
|
||||
// Update metrics for affected clusters (they lost keywords)
|
||||
if (!empty($cluster_ids)) {
|
||||
foreach (array_unique($cluster_ids) as $cluster_id) {
|
||||
if ($cluster_id) {
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => "Successfully unmapped {$unmapped_count} keyword(s) from clusters",
|
||||
'unmapped_count' => $unmapped_count
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically create or link a taxonomy term when a new cluster is created.
|
||||
*
|
||||
* @param int $cluster_id The cluster ID from wp_igny8_clusters.
|
||||
*/
|
||||
function igny8_auto_create_cluster_term($cluster_id) {
|
||||
global $wpdb;
|
||||
|
||||
// 1. Validate cluster
|
||||
$cluster = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT cluster_name, cluster_term_id FROM {$wpdb->prefix}igny8_clusters WHERE id = %d",
|
||||
$cluster_id
|
||||
));
|
||||
|
||||
if (!$cluster) {
|
||||
error_log("Igny8: Cluster not found for ID $cluster_id.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Skip if already mapped
|
||||
if (!empty($cluster->cluster_term_id)) {
|
||||
error_log("Igny8: Cluster $cluster_id already linked to term {$cluster->cluster_term_id}.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Ensure taxonomy exists
|
||||
if (!taxonomy_exists('clusters') && function_exists('igny8_register_taxonomies')) {
|
||||
igny8_register_taxonomies();
|
||||
}
|
||||
|
||||
// 4. Create or find existing term
|
||||
$term_result = wp_insert_term(
|
||||
sanitize_text_field($cluster->cluster_name),
|
||||
'clusters',
|
||||
['slug' => sanitize_title($cluster->cluster_name)]
|
||||
);
|
||||
|
||||
if (is_wp_error($term_result)) {
|
||||
// If term exists, fetch it
|
||||
$existing = get_term_by('name', $cluster->cluster_name, 'clusters');
|
||||
$term_id = $existing ? $existing->term_id : 0;
|
||||
} else {
|
||||
$term_id = $term_result['term_id'];
|
||||
}
|
||||
|
||||
// 5. Save term ID back to cluster table
|
||||
if ($term_id > 0) {
|
||||
$wpdb->update(
|
||||
"{$wpdb->prefix}igny8_clusters",
|
||||
['cluster_term_id' => $term_id],
|
||||
['id' => $cluster_id],
|
||||
['%d'],
|
||||
['%d']
|
||||
);
|
||||
error_log("Igny8: Created and linked taxonomy term $term_id for cluster $cluster_id.");
|
||||
} else {
|
||||
error_log("Igny8: Failed to link taxonomy term for cluster $cluster_id.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically update taxonomy term when a cluster name is changed/updated.
|
||||
*
|
||||
* @param int $cluster_id The cluster ID from wp_igny8_clusters.
|
||||
*/
|
||||
function igny8_auto_update_cluster_term($cluster_id) {
|
||||
global $wpdb;
|
||||
|
||||
// 1. Validate cluster
|
||||
$cluster = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT cluster_name, cluster_term_id FROM {$wpdb->prefix}igny8_clusters WHERE id = %d",
|
||||
$cluster_id
|
||||
));
|
||||
|
||||
if (!$cluster) {
|
||||
error_log("Igny8: Cluster not found for ID $cluster_id.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Skip if no term linked
|
||||
if (empty($cluster->cluster_term_id)) {
|
||||
error_log("Igny8: Cluster $cluster_id has no linked taxonomy term.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Ensure taxonomy exists
|
||||
if (!taxonomy_exists('clusters') && function_exists('igny8_register_taxonomies')) {
|
||||
igny8_register_taxonomies();
|
||||
}
|
||||
|
||||
// 4. Get the existing term
|
||||
$term = get_term($cluster->cluster_term_id, 'clusters');
|
||||
if (is_wp_error($term) || !$term) {
|
||||
error_log("Igny8: Taxonomy term {$cluster->cluster_term_id} not found for cluster $cluster_id.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. Check if name has changed
|
||||
if ($term->name === $cluster->cluster_name) {
|
||||
error_log("Igny8: Cluster $cluster_id name unchanged, skipping taxonomy update.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 6. Update the term name and slug
|
||||
$update_result = wp_update_term(
|
||||
$cluster->cluster_term_id,
|
||||
'clusters',
|
||||
[
|
||||
'name' => sanitize_text_field($cluster->cluster_name),
|
||||
'slug' => sanitize_title($cluster->cluster_name)
|
||||
]
|
||||
);
|
||||
|
||||
if (is_wp_error($update_result)) {
|
||||
error_log("Igny8: Failed to update taxonomy term for cluster $cluster_id: " . $update_result->get_error_message());
|
||||
} else {
|
||||
error_log("Igny8: Successfully updated taxonomy term {$cluster->cluster_term_id} for cluster $cluster_id.");
|
||||
}
|
||||
}
|
||||
|
||||
// Hook registration for automatic cluster term creation
|
||||
// Hook moved to sync-hooks.php
|
||||
|
||||
/**
|
||||
* Handle content association/disassociation with cluster taxonomy terms
|
||||
*/
|
||||
function igny8_handle_content_cluster_association($object_id, $terms, $tt_ids, $taxonomy) {
|
||||
// Only process clusters taxonomy
|
||||
if ($taxonomy !== 'clusters') {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Get all cluster IDs that have terms in this taxonomy update
|
||||
$cluster_ids = [];
|
||||
|
||||
foreach ($terms as $term) {
|
||||
if (is_numeric($term)) {
|
||||
$term_id = $term;
|
||||
} else {
|
||||
$term_obj = get_term_by('slug', $term, 'clusters');
|
||||
$term_id = $term_obj ? $term_obj->term_id : null;
|
||||
}
|
||||
|
||||
if ($term_id) {
|
||||
// Find cluster that has this term_id
|
||||
$cluster_id = $wpdb->get_var($wpdb->prepare("
|
||||
SELECT id FROM {$wpdb->prefix}igny8_clusters
|
||||
WHERE cluster_term_id = %d
|
||||
", $term_id));
|
||||
|
||||
if ($cluster_id) {
|
||||
$cluster_ids[] = $cluster_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update metrics for all affected clusters
|
||||
foreach (array_unique($cluster_ids) as $cluster_id) {
|
||||
igny8_update_cluster_metrics($cluster_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Hook registration for automatic cluster metrics updates when content is associated/disassociated with cluster terms
|
||||
// Hook moved to sync-hooks.php
|
||||
|
||||
/**
|
||||
* Update task metrics including word count and meta sync
|
||||
*/
|
||||
function igny8_update_task_metrics($task_id) {
|
||||
global $wpdb;
|
||||
$post_id = $wpdb->get_var($wpdb->prepare("SELECT assigned_post_id FROM {$wpdb->prefix}igny8_tasks WHERE id = %d", $task_id));
|
||||
|
||||
if ($post_id) {
|
||||
$content = get_post_field('post_content', $post_id);
|
||||
$word_count = str_word_count(strip_tags($content));
|
||||
update_post_meta($post_id, '_igny8_word_count', $word_count);
|
||||
|
||||
$wpdb->update("{$wpdb->prefix}igny8_tasks", ['word_count' => $word_count], ['id' => $task_id]);
|
||||
}
|
||||
}
|
||||
99
igny8-ai-seo-wp-plugin/flows/sync-hooks.php
Normal file
99
igny8-ai-seo-wp-plugin/flows/sync-hooks.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* ==========================
|
||||
* 🔐 IGNY8 FILE RULE HEADER
|
||||
* ==========================
|
||||
* @file : sync-hooks.php
|
||||
* @location : /flows/sync-hooks.php
|
||||
* @type : Function Library
|
||||
* @scope : Global
|
||||
* @allowed : Hook definitions, workflow registration, automation triggers
|
||||
* @reusability : Globally Reusable
|
||||
* @notes : Central hook definitions for all automation workflows
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// AUTOMATION WORKFLOW HOOKS
|
||||
// ===================================================================
|
||||
|
||||
/**
|
||||
* Keyword lifecycle hooks - trigger cluster updates
|
||||
*/
|
||||
add_action('igny8_keyword_added', 'igny8_handle_keyword_cluster_update', 10, 2);
|
||||
add_action('igny8_keyword_updated', 'igny8_handle_keyword_cluster_update', 10, 2);
|
||||
add_action('igny8_keyword_deleted', 'igny8_handle_keyword_cluster_update', 10, 2);
|
||||
|
||||
/**
|
||||
* Cluster management hooks
|
||||
*/
|
||||
add_action('igny8_cluster_added', 'igny8_auto_create_cluster_term', 10, 1);
|
||||
add_action('igny8_cluster_updated', 'igny8_auto_update_cluster_term', 10, 1);
|
||||
add_action('set_object_terms', 'igny8_handle_content_cluster_association', 10, 4);
|
||||
|
||||
/**
|
||||
* WordPress post publishing hooks - update keyword status when content is published
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// AJAX WORKFLOW HOOKS
|
||||
// ===================================================================
|
||||
|
||||
/**
|
||||
* Import and bulk operations
|
||||
*/
|
||||
add_action('wp_ajax_igny8_import_keywords', 'igny8_ajax_import_keywords');
|
||||
|
||||
/**
|
||||
* Planner → Writer bridge operations
|
||||
*/
|
||||
add_action('wp_ajax_igny8_create_task_from_idea', 'igny8_create_task_from_idea_ajax');
|
||||
add_action('wp_ajax_igny8_bulk_create_tasks_from_ideas', 'igny8_bulk_create_tasks_from_ideas_ajax');
|
||||
|
||||
/**
|
||||
* Bulk keyword operations
|
||||
*/
|
||||
add_action('wp_ajax_igny8_bulk_delete_keywords', 'igny8_ajax_bulk_delete_keywords');
|
||||
add_action('wp_ajax_igny8_bulk_map_keywords', 'igny8_ajax_bulk_map_keywords');
|
||||
add_action('wp_ajax_igny8_bulk_unmap_keywords', 'igny8_ajax_bulk_unmap_keywords');
|
||||
|
||||
/**
|
||||
* Bulk record operations
|
||||
*/
|
||||
add_action('wp_ajax_igny8_delete_bulk_records', 'igny8_delete_bulk_records');
|
||||
|
||||
// ===================================================================
|
||||
// AI QUEUE PROCESSING - DEPRECATED (MOVED TO CRON MANAGER)
|
||||
// ===================================================================
|
||||
|
||||
// Note: AI queue processing is now handled by the smart automation system
|
||||
// in core/cron/igny8-cron-master-dispatcher.php and core/cron/igny8-cron-handlers.php
|
||||
|
||||
// ===================================================================
|
||||
// AI AUTOMATION CRON JOBS - DEPRECATED (MOVED TO CRON MANAGER)
|
||||
// ===================================================================
|
||||
|
||||
// Note: All automation cron jobs are now handled by the smart automation system
|
||||
// in core/cron/igny8-cron-master-dispatcher.php and core/cron/igny8-cron-handlers.php
|
||||
|
||||
// All cron handlers have been moved to core/cron/igny8-cron-handlers.php
|
||||
|
||||
// ===================================================================
|
||||
// WRITER MODULE HOOKS
|
||||
// ===================================================================
|
||||
|
||||
/**
|
||||
* Hook into draft creation and recalculate metrics
|
||||
*/
|
||||
add_action('igny8_task_draft_created', function($task_id, $post_id) {
|
||||
igny8_update_task_metrics($task_id);
|
||||
}, 10, 2);
|
||||
Reference in New Issue
Block a user