__('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); } }