'ayudawp_acs_sanitize_settings', ) ); } add_action( 'admin_init', 'ayudawp_acs_settings_init' ); /** * Sanitize settings callback * * @param array $input Raw form input. * @return array Sanitized settings. */ function ayudawp_acs_sanitize_settings( $input ) { if ( ! is_array( $input ) ) { return array(); } // Get current settings to preserve values for fields not in the input. $current_settings = get_option( 'ayudawp_acs_settings', array() ); $sanitized = array( 'global_search' => isset( $input['global_search'] ) ? sanitize_text_field( $input['global_search'] ) : ( $current_settings['global_search'] ?? 'yes' ), 'global_ai_input' => isset( $input['global_ai_input'] ) ? sanitize_text_field( $input['global_ai_input'] ) : ( $current_settings['global_ai_input'] ?? 'yes' ), 'global_ai_train' => isset( $input['global_ai_train'] ) ? sanitize_text_field( $input['global_ai_train'] ) : ( $current_settings['global_ai_train'] ?? 'yes' ), 'include_legal_text' => ( isset( $input['include_legal_text'] ) && 'yes' === $input['include_legal_text'] ) ? 'yes' : 'no', 'create_physical_robots' => ( isset( $input['create_physical_robots'] ) && 'yes' === $input['create_physical_robots'] ) ? 'yes' : 'no', 'bot_settings' => array(), 'custom_bots' => array(), ); // Sanitize bot settings. if ( isset( $input['bot_settings'] ) && is_array( $input['bot_settings'] ) ) { foreach ( $input['bot_settings'] as $bot => $bot_data ) { $sanitized['bot_settings'][ sanitize_text_field( $bot ) ] = array( 'search' => isset( $bot_data['search'] ) ? sanitize_text_field( $bot_data['search'] ) : '', 'ai_input' => isset( $bot_data['ai_input'] ) ? sanitize_text_field( $bot_data['ai_input'] ) : '', 'ai_train' => isset( $bot_data['ai_train'] ) ? sanitize_text_field( $bot_data['ai_train'] ) : '', ); } } // Sanitize custom bots. if ( isset( $input['custom_bots'] ) && is_array( $input['custom_bots'] ) ) { foreach ( $input['custom_bots'] as $bot ) { if ( ! empty( $bot['name'] ) ) { $sanitized['custom_bots'][] = array( 'name' => sanitize_text_field( $bot['name'] ), 'search' => isset( $bot['search'] ) ? sanitize_text_field( $bot['search'] ) : '', 'ai_input' => isset( $bot['ai_input'] ) ? sanitize_text_field( $bot['ai_input'] ) : '', 'ai_train' => isset( $bot['ai_train'] ) ? sanitize_text_field( $bot['ai_train'] ) : '', ); } } } return $sanitized; } /** * Enqueue admin styles and scripts * * @param string $hook Current admin page hook. */ function ayudawp_acs_admin_assets( $hook ) { if ( 'settings_page_ai-content-signals' !== $hook ) { return; } // Load Thickbox for plugin install modals in promo banner. add_thickbox(); // Enqueue CSS. wp_enqueue_style( 'ayudawp-acs-admin', AYUDAWP_ACS_PLUGIN_URL . 'assets/admin.css', array(), AYUDAWP_ACS_VERSION ); // Enqueue JavaScript. wp_enqueue_script( 'ayudawp-acs-admin', AYUDAWP_ACS_PLUGIN_URL . 'assets/admin.js', array( 'jquery' ), AYUDAWP_ACS_VERSION, true ); // Pass translations to JavaScript. wp_localize_script( 'ayudawp-acs-admin', 'ayudawpAcsL10n', array( 'botUserAgentPlaceholder' => __( 'Bot User-Agent (e.g., NewAIBot)', 'ai-content-signals' ), 'searchGlobal' => __( 'Search: Global', 'ai-content-signals' ), 'searchYes' => __( 'Search: Yes', 'ai-content-signals' ), 'searchNo' => __( 'Search: No', 'ai-content-signals' ), 'aiInputGlobal' => __( 'AI Input: Global', 'ai-content-signals' ), 'aiInputYes' => __( 'AI Input: Yes', 'ai-content-signals' ), 'aiInputNo' => __( 'AI Input: No', 'ai-content-signals' ), 'aiTrainGlobal' => __( 'AI Train: Global', 'ai-content-signals' ), 'aiTrainYes' => __( 'AI Train: Yes', 'ai-content-signals' ), 'aiTrainNo' => __( 'AI Train: No', 'ai-content-signals' ), 'remove' => __( 'Remove', 'ai-content-signals' ), 'confirmRestore' => __( 'Are you sure you want to restore all settings to their default values? This cannot be undone.', 'ai-content-signals' ), ) ); } add_action( 'admin_enqueue_scripts', 'ayudawp_acs_admin_assets' ); /** * Get predefined list of common AI bots * * @return array Associative array of bot_key => bot_label. */ function ayudawp_acs_get_predefined_bots() { $bots = array( 'GPTBot' => 'OpenAI GPTBot', 'OAI-SearchBot' => 'OpenAI Search Bot', 'ChatGPT-User' => 'ChatGPT User Agent', 'ClaudeBot' => 'Anthropic ClaudeBot', 'Claude-Web' => 'Claude Web Crawler', 'anthropic-ai' => 'Anthropic AI', 'PerplexityBot' => 'Perplexity Bot', 'Perplexity-User' => 'Perplexity User Agent', 'Google-Extended' => 'Google Extended (Gemini)', 'GoogleOther' => 'Google Other Bots', 'CCBot' => 'Common Crawl Bot', 'cohere-ai' => 'Cohere AI', 'Bytespider' => 'ByteDance (TikTok)', 'Amazonbot' => 'Amazon Bot', 'Applebot-Extended' => 'Apple Extended', 'meta-externalagent' => 'Meta External Agent', 'FacebookBot' => 'Meta/Facebook Bot', 'DuckAssistBot' => 'DuckDuckGo AI', 'AI2Bot' => 'Allen Institute AI2', 'MistralAI-User' => 'Mistral AI', 'Diffbot' => 'Diffbot', 'ImagesiftBot' => 'ImagesiftBot', 'Omgilibot' => 'Omgili Bot', 'YouBot' => 'You.com Bot', 'Timpibot' => 'Timpi Bot', 'DeepSeekBot' => 'DeepSeek AI', 'GrokBot' => 'xAI Grok', 'PanguBot' => 'Huawei Pangu', ); /** * Filter the predefined bots list. * * Allows other plugins or themes to add or remove bots * from the predefined list without modifying plugin code. * * @since 1.2.0 * * @param array $bots Associative array of bot_key => bot_label. */ return apply_filters( 'ayudawp_acs_predefined_bots', $bots ); } /** * Check if file system is accessible * * @return bool True if WP_Filesystem is available. */ function ayudawp_acs_check_filesystem() { global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } return ! empty( $wp_filesystem ); } /** * Display admin notices about robots.txt status */ function ayudawp_acs_admin_notices() { $screen = get_current_screen(); if ( ! $screen || 'settings_page_ai-content-signals' !== $screen->id ) { return; } if ( ! current_user_can( 'manage_options' ) ) { return; } if ( ! ayudawp_acs_check_filesystem() ) { return; } global $wp_filesystem; $robots_file = ABSPATH . 'robots.txt'; $has_physical = $wp_filesystem->exists( $robots_file ); $robots_url = $has_physical ? home_url( '/robots.txt' ) : home_url( '/?robots=1' ); if ( $has_physical ) { $is_readable = $wp_filesystem->is_readable( $robots_file ); $is_writable = $wp_filesystem->is_writable( $robots_file ); if ( $is_readable && $is_writable ) { echo '
'; echo '' . esc_html__( 'Physical robots.txt detected:', 'ai-content-signals' ) . ' '; esc_html_e( 'File is readable and writable. Content Signals will be appended to your existing robots.txt file.', 'ai-content-signals' ); echo ' '; esc_html_e( 'If you uninstall the plugin, the file will remain but Content Signals lines will be automatically removed.', 'ai-content-signals' ); echo ' ' . esc_html__( 'View robots.txt', 'ai-content-signals' ) . ' ↗'; echo '
';
echo '' . esc_html__( 'Warning - Cannot write to robots.txt!', 'ai-content-signals' ) . '
';
if ( ! $is_readable && ! $is_writable ) {
esc_html_e( 'Physical robots.txt exists but is NOT readable or writable. Content Signals cannot be applied to the file.', 'ai-content-signals' );
echo '
';
esc_html_e( 'Please change file permissions to 644 before configuring settings.', 'ai-content-signals' );
} elseif ( ! $is_readable ) {
esc_html_e( 'Physical robots.txt exists but is NOT readable. Content Signals cannot read the file.', 'ai-content-signals' );
echo '
';
esc_html_e( 'Please change file permissions to 644 before configuring settings.', 'ai-content-signals' );
} else {
esc_html_e( 'Physical robots.txt exists but is NOT writable. Content Signals cannot be written to the file.', 'ai-content-signals' );
echo '
';
esc_html_e( 'Please change file permissions to 644 before configuring settings.', 'ai-content-signals' );
}
echo ' ' . esc_html__( 'View robots.txt', 'ai-content-signals' ) . ' ↗';
echo '
'; echo '' . esc_html__( 'Physical robots.txt will be created:', 'ai-content-signals' ) . ' '; esc_html_e( 'You have enabled the option to create a physical robots.txt. It will be created with basic WordPress rules when you save settings.', 'ai-content-signals' ); echo ' ' . esc_html__( 'View current virtual robots.txt', 'ai-content-signals' ) . ' ↗'; echo '
'; echo '' . esc_html__( 'Cannot create robots.txt:', 'ai-content-signals' ) . ' '; esc_html_e( 'The root directory is not writable. Please check directory permissions or contact your hosting provider.', 'ai-content-signals' ); echo '
'; echo '' . esc_html__( 'Virtual robots.txt mode:', 'ai-content-signals' ) . ' '; esc_html_e( 'No physical robots.txt detected. Content Signals are being added to the WordPress virtual robots.txt. You can enable the option below to create a physical file with basic rules.', 'ai-content-signals' ); echo ' ' . esc_html__( 'View virtual robots.txt', 'ai-content-signals' ) . ' ↗'; echo '