203 lines
5.9 KiB
PHP
203 lines
5.9 KiB
PHP
<?php
|
|
/**
|
|
* Link Insertion Queue
|
|
*
|
|
* Queues and processes link recommendations from IGNY8 Linker
|
|
*
|
|
* @package Igny8Bridge
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Queue link insertion
|
|
*
|
|
* @param array $link_data Link data
|
|
* @return int|false Queue ID or false on failure
|
|
*/
|
|
function igny8_queue_link_insertion($link_data) {
|
|
if (!igny8_is_connection_enabled()) {
|
|
return false;
|
|
}
|
|
|
|
$queue = get_option('igny8_link_queue', array());
|
|
|
|
$queue_item = array(
|
|
'id' => uniqid('link_', true),
|
|
'post_id' => intval($link_data['post_id']),
|
|
'target_url' => esc_url_raw($link_data['target_url']),
|
|
'anchor' => sanitize_text_field($link_data['anchor']),
|
|
'source' => sanitize_text_field($link_data['source'] ?? 'igny8_linker'),
|
|
'priority' => sanitize_text_field($link_data['priority'] ?? 'normal'),
|
|
'status' => 'pending',
|
|
'created_at' => $link_data['created_at'] ?? current_time('mysql'),
|
|
'attempts' => 0
|
|
);
|
|
|
|
$queue[] = $queue_item;
|
|
|
|
// Limit queue size (keep last 1000 items)
|
|
if (count($queue) > 1000) {
|
|
$queue = array_slice($queue, -1000);
|
|
}
|
|
|
|
update_option('igny8_link_queue', $queue);
|
|
|
|
// Trigger processing if not already scheduled
|
|
if (!wp_next_scheduled('igny8_process_link_queue')) {
|
|
wp_schedule_single_event(time() + 60, 'igny8_process_link_queue');
|
|
}
|
|
|
|
return $queue_item['id'];
|
|
}
|
|
|
|
/**
|
|
* Process link insertion queue
|
|
*/
|
|
function igny8_process_link_queue() {
|
|
if (!igny8_is_connection_enabled()) {
|
|
return;
|
|
}
|
|
|
|
if (function_exists('igny8_is_module_enabled') && !igny8_is_module_enabled('linker')) {
|
|
return;
|
|
}
|
|
|
|
$queue = get_option('igny8_link_queue', array());
|
|
|
|
if (empty($queue)) {
|
|
return;
|
|
}
|
|
|
|
// Process up to 10 items per run
|
|
$processed = 0;
|
|
$max_per_run = 10;
|
|
|
|
foreach ($queue as $key => $item) {
|
|
if ($processed >= $max_per_run) {
|
|
break;
|
|
}
|
|
|
|
if ($item['status'] !== 'pending') {
|
|
continue;
|
|
}
|
|
|
|
$result = igny8_insert_link_into_post($item);
|
|
|
|
if ($result['success']) {
|
|
$queue[$key]['status'] = 'completed';
|
|
$queue[$key]['completed_at'] = current_time('mysql');
|
|
} else {
|
|
$queue[$key]['attempts']++;
|
|
|
|
if ($queue[$key]['attempts'] >= 3) {
|
|
$queue[$key]['status'] = 'failed';
|
|
$queue[$key]['error'] = $result['error'] ?? 'Unknown error';
|
|
}
|
|
}
|
|
|
|
$processed++;
|
|
}
|
|
|
|
update_option('igny8_link_queue', $queue);
|
|
|
|
// Schedule next run if there are pending items
|
|
$has_pending = false;
|
|
foreach ($queue as $item) {
|
|
if ($item['status'] === 'pending') {
|
|
$has_pending = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($has_pending && !wp_next_scheduled('igny8_process_link_queue')) {
|
|
wp_schedule_single_event(time() + 60, 'igny8_process_link_queue');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Insert link into post content
|
|
*
|
|
* @param array $link_item Link queue item
|
|
* @return array Result
|
|
*/
|
|
function igny8_insert_link_into_post($link_item) {
|
|
$post_id = $link_item['post_id'];
|
|
$target_url = $link_item['target_url'];
|
|
$anchor = $link_item['anchor'];
|
|
|
|
$post = get_post($post_id);
|
|
|
|
if (!$post) {
|
|
return array('success' => false, 'error' => 'Post not found');
|
|
}
|
|
|
|
$content = $post->post_content;
|
|
|
|
// Check if link already exists
|
|
if (strpos($content, $target_url) !== false) {
|
|
return array('success' => true, 'message' => 'Link already exists');
|
|
}
|
|
|
|
// Find first occurrence of anchor text not already in a link
|
|
$anchor_escaped = preg_quote($anchor, '/');
|
|
|
|
// Pattern to find anchor text that's not inside an <a> tag
|
|
// This is a simplified approach - find anchor text and check if it's not in a link
|
|
$pattern = '/\b' . $anchor_escaped . '\b/i';
|
|
|
|
if (preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE)) {
|
|
foreach ($matches[0] as $match) {
|
|
$position = $match[1];
|
|
$length = strlen($match[0]);
|
|
|
|
// Check if this position is inside an <a> tag
|
|
$before = substr($content, 0, $position);
|
|
$after = substr($content, $position + $length);
|
|
|
|
// Count unclosed <a> tags before this position
|
|
$open_tags = substr_count($before, '<a');
|
|
$close_tags = substr_count($before, '</a>');
|
|
|
|
// If not inside a link, replace it
|
|
if ($open_tags <= $close_tags) {
|
|
$link_html = '<a href="' . esc_url($target_url) . '">' . esc_html($anchor) . '</a>';
|
|
$new_content = substr_replace($content, $link_html, $position, $length);
|
|
|
|
$result = wp_update_post(array(
|
|
'ID' => $post_id,
|
|
'post_content' => $new_content
|
|
));
|
|
|
|
if ($result && !is_wp_error($result)) {
|
|
return array('success' => true, 'message' => 'Link inserted');
|
|
} else {
|
|
return array('success' => false, 'error' => 'Failed to update post');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If anchor not found, append link at end of content
|
|
$link_html = "\n\n<p><a href=\"" . esc_url($target_url) . "\">" . esc_html($anchor) . "</a></p>";
|
|
$new_content = $content . $link_html;
|
|
|
|
$result = wp_update_post(array(
|
|
'ID' => $post_id,
|
|
'post_content' => $new_content
|
|
));
|
|
|
|
if ($result && !is_wp_error($result)) {
|
|
return array('success' => true, 'message' => 'Link appended');
|
|
} else {
|
|
return array('success' => false, 'error' => 'Failed to update post');
|
|
}
|
|
}
|
|
|
|
// Register cron hook
|
|
add_action('igny8_process_link_queue', 'igny8_process_link_queue');
|
|
|