exists( ARTTE_ROBOTS_FILE ) || ! $filesystem->is_file( ARTTE_ROBOTS_FILE ) ) { return false; } if ( ! $filesystem->is_readable( ARTTE_ROBOTS_FILE ) ) { return false; } $content = $filesystem->get_contents( ARTTE_ROBOTS_FILE ); return false === $content ? false : $content; } /** * Write the physical robots.txt file. * * @param string $content Robots.txt content. * @return bool True on success, false on failure. */ function artte_write_robots_file( $content ) { $filesystem = artte_get_filesystem(); if ( ! $filesystem ) { return false; } return $filesystem->put_contents( ARTTE_ROBOTS_FILE, $content, FS_CHMOD_FILE ); } /** * Normalize robots.txt content before saving. * * Robots.txt is configuration/plain text, so this function intentionally * does not use sanitize_textarea_field(). That sanitizer can modify valid * robots.txt directives. * * @param string $content Raw submitted content. * @return string Normalized content. */ function artte_sanitize_robots_content( $content ) { $content = str_replace( "\0", '', $content ); $content = str_replace( "\r\n", "\n", $content ); $content = str_replace( "\r", "\n", $content ); $content = trim( $content ); return $content . "\n"; } /** * Get the submitted robots.txt content. * * @return string Sanitized and normalized robots.txt content. */ function artte_get_submitted_robots_content() { $content = filter_input( INPUT_POST, 'robots_content', FILTER_UNSAFE_RAW ); if ( ! is_string( $content ) ) { return ''; } return artte_sanitize_robots_content( wp_unslash( $content ) ); } /** * Get the submitted admin action. * * @return string Sanitized action value. */ function artte_get_submitted_action() { $action = filter_input( INPUT_POST, 'artte_action', FILTER_UNSAFE_RAW ); if ( ! is_string( $action ) ) { return ''; } return sanitize_key( $action ); } /** * Determine whether the robots.txt form was submitted. * * @return bool True when the form was submitted. */ function artte_is_robots_form_submitted() { $action = filter_input( INPUT_POST, 'artte_action', FILTER_UNSAFE_RAW ); $content = filter_input( INPUT_POST, 'robots_content', FILTER_UNSAFE_RAW ); return null !== $action || null !== $content; } /** * Filter WordPress' virtual robots.txt output. * * A physical robots.txt file is normally served by the web server before * WordPress is loaded. When no physical file exists, this filter provides * the editor's content through WordPress. * * @param string $output Existing robots.txt output. * @param bool $public Whether the site is considered public. * @return string Robots.txt output. */ function artte_output_custom_robots_txt( $output, $public ) { if ( ! $public ) { return "User-agent: *\nDisallow: /\n"; } $content = artte_read_robots_file(); if ( false !== $content ) { return $content; } return artte_get_default_robots_content(); } add_filter( 'robots_txt', 'artte_output_custom_robots_txt', 10, 2 ); /** * Add the Robots.txt editor admin menu. * * @return void */ function artte_add_admin_menu() { add_menu_page( __( 'Robots.txt Editor', 'admin-robots-txt-editor' ), __( 'Robots.txt', 'admin-robots-txt-editor' ), 'manage_options', 'admin-robots-txt', 'artte_render_robots_editor', 'dashicons-media-text', 91 ); } add_action( 'admin_menu', 'artte_add_admin_menu' ); /** * Enqueue admin assets for the plugin screen. * * @param string $hook_suffix Current admin page hook suffix. * @return void */ function artte_enqueue_admin_assets( $hook_suffix ) { if ( 'toplevel_page_admin-robots-txt' !== $hook_suffix ) { return; } wp_enqueue_script( 'artte-admin', plugins_url( 'assets/admin.js', __FILE__ ), array(), '1.0.1', true ); wp_localize_script( 'artte-admin', 'artteAdmin', array( 'confirmReset' => __( 'Are you sure you want to reset robots.txt to the default content?', 'admin-robots-txt-editor' ), ) ); } add_action( 'admin_enqueue_scripts', 'artte_enqueue_admin_assets' ); /** * Render the Robots.txt editor page. * * @return void */ function artte_render_robots_editor() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to access this page.', 'admin-robots-txt-editor' ) ); } $message = ''; $success = false; /* * Process the submitted form. * * filter_input() is used instead of directly accessing $_POST so that * the submitted values are retrieved through PHP's input filtering API. */ if ( artte_is_robots_form_submitted() ) { check_admin_referer( 'artte_update_robots', 'artte_nonce' ); $action = artte_get_submitted_action(); if ( 'save' === $action ) { $content = artte_get_submitted_robots_content(); if ( artte_write_robots_file( $content ) ) { $message = __( 'robots.txt has been updated successfully.', 'admin-robots-txt-editor' ); $success = true; } else { $message = __( 'Unable to write robots.txt. Check the web server file permissions.', 'admin-robots-txt-editor' ); } } elseif ( 'reset' === $action ) { $default = artte_get_default_robots_content(); if ( artte_write_robots_file( $default ) ) { $message = __( 'robots.txt has been reset to the default content.', 'admin-robots-txt-editor' ); $success = true; } else { $message = __( 'Unable to reset robots.txt. Check the web server file permissions.', 'admin-robots-txt-editor' ); } } } $robots_content = artte_read_robots_file(); if ( false === $robots_content ) { $robots_content = artte_get_default_robots_content(); } $robots_url = home_url( '/robots.txt' ); ?>

' . esc_html( $robots_url ) . '' ); ?>