__('Permission Denied.', 'advanced-redirect-manager')]);
}
global $wpdb;
$post_types = get_post_types(['public' => true]);
if (empty($post_types)) {
wp_send_json_success(['message' => __('No public post types found to scan.', 'advanced-redirect-manager'), 'finished' => true]);
}
$post_types_placeholders = implode(', ', array_fill(0, count($post_types), '%s'));
$posts_with_links = $wpdb->get_results(
$wpdb->prepare(
"SELECT ID, post_title FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type IN ({$post_types_placeholders}) AND post_content LIKE %s",
array_merge(array_values($post_types), ['% __('Scan complete. No posts or pages containing links were found.', 'advanced-redirect-manager'), 'finished' => true]);
}
wp_send_json_success(['jobs' => $posts_with_links]);
}
/**
* AJAX handler to process a single post/page (a "chunk").
* Finds all links in the content and checks their HTTP status.
*/
public function ajax_scanner_chunk() {
check_ajax_referer('ncb_arm_admin_ajax_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'Permission Denied.']);
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
if (!$post_id) {
wp_send_json_error(['message' => 'Invalid Post ID.']);
}
$scan_types = [];
if ( isset( $_POST['scan_types'] ) && is_array( $_POST['scan_types'] ) ) {
// Sanitize each value from the input array.
$scan_types = array_map( 'sanitize_key', wp_unslash( $_POST['scan_types'] ) );
}
$scan_internal = in_array( 'internal', $scan_types, true );
$scan_external = in_array( 'external', $scan_types, true );
$post = get_post($post_id);
if (!$post) {
wp_send_json_error(['message' => 'Post not found.']);
}
$content = $post->post_content;
$found_links = [];
$site_url = home_url();
if (preg_match_all('/]*?\s+)?href=(["\'])(.*?)\1/', $content, $matches)) {
$urls = array_unique($matches[2]);
foreach ($urls as $url) {
if (empty($url) || str_starts_with($url, '#') || str_starts_with($url, 'mailto:') || str_starts_with($url, 'tel:') || str_starts_with($url, 'javascript:')) {
continue;
}
$site_host = wp_parse_url($site_url, PHP_URL_HOST);
$link_host = wp_parse_url($url, PHP_URL_HOST);
// Un link è interno se non ha un host (es. /pagina) o se il suo host è identico a quello del sito.
$is_internal = empty($link_host) || (strcasecmp($link_host, $site_host) === 0);
// Se è un link interno e NON dobbiamo controllare gli interni, salta.
if ($is_internal && !$scan_internal) {
continue;
}
// Se è un link esterno e NON dobbiamo controllare gli esterni, salta.
if (!$is_internal && !$scan_external) {
continue;
}
// Esegui il controllo dello stato del link
$status_code = $this->check_link_status($url);
$found_links[] = [
'url' => esc_url_raw($url),
'status' => $status_code,
'status_text' => $status_code ? get_status_header_desc($status_code) : 'Connection Error',
'post_title' => $post->post_title,
'post_id' => $post->ID,
'edit_link' => get_edit_post_link($post->ID, 'raw'),
];
}
}
wp_send_json_success(['links' => $found_links]);
}
/**
* Checks the HTTP status of a given URL using WordPress HTTP API.
*
* @param string $url The URL to check.
* @return int The HTTP status code (0 for connection errors).
*/
private function check_link_status($url) {
// Rendi l'URL assoluto se è relativo
if (substr($url, 0, 1) === '/' || (strpos($url, '://') === false && substr($url, 0, 1) !== '#')) {
$url = home_url($url);
}
// Un User-Agent che simula un browser comune.
$browser_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36';
$args = [
'timeout' => 10,
'redirection' => 5,
'sslverify' => apply_filters('ncb_arm_scanner_sslverify', true),
'user-agent' => $browser_user_agent,
];
// Usiamo wp_remote_head per essere più veloci (non scarica il body)
$response = wp_remote_head($url, $args);
if (is_wp_error($response)) {
// Potrebbe essere un errore cURL, DNS, timeout, etc.
return 0; // Codice personalizzato per "Errore di connessione"
}
return wp_remote_retrieve_response_code($response);
}
}