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 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 tag $before = substr($content, 0, $position); $after = substr($content, $position + $length); // Count unclosed tags before this position $open_tags = substr_count($before, ''); // If not inside a link, replace it if ($open_tags <= $close_tags) { $link_html = '' . esc_html($anchor) . ''; $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
"; $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');