Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
perpending
/
wp-content
/
plugins
/
seo-by-rank-math
/
includes
/
modules
/
llms
:
class-llms-txt.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * The llms.txt module. * * @package RankMath * @subpackage RankMath\LLMS */ namespace RankMath\LLMS; use RankMath\Helper; use RankMath\Traits\Hooker; use RankMath\Helpers\Arr; use RankMath\Sitemap\Sitemap; use RankMath\Sitemap\Router; use RankMath\Helpers\Url; use WP_Query; defined( 'ABSPATH' ) || exit; /** * LLMS_Txt class. */ class LLMS_Txt { use Hooker; /** * Class constructor. * * Registers hooks and filters for the llms.txt module. */ public function __construct() { $this->action( 'init', 'add_rewrite_rule' ); $this->action( 'template_redirect', 'maybe_serve_llms_txt' ); $this->filter( 'rank_math/settings/general', 'add_settings' ); $this->action( 'wp_loaded', 'remove_canonical_redirect' ); } /** * Remove the canonical redirect for the llms.txt file. * * @hook wp_loaded * @return void */ public function remove_canonical_redirect() { if ( strpos( Url::get_current_url(), '/llms.txt' ) !== false ) { remove_filter( 'template_redirect', 'redirect_canonical' ); } } /** * Add the llms.txt settings tab to the General settings panel. * * @hook rank_math/settings/general * * @param array $tabs Option panel tabs. * @return array Modified tabs array with llms.txt tab added. */ public function add_settings( $tabs ) { Arr::insert( $tabs, [ 'llms' => [ 'icon' => 'rm-icon rm-icon-bot', 'title' => esc_html__( 'Edit llms.txt', 'rank-math' ), 'desc' => esc_html__( 'Configure your llms.txt file for custom crawling/indexing rules.', 'rank-math' ), 'file' => __DIR__ . '/options.php', 'classes' => 'rank-math-advanced-option', 'json' => [ 'llmsUrl' => esc_url( home_url( '/llms.txt' ) ), ], ], ], 5 ); return $tabs; } /** * Add the rewrite rule and query var for llms.txt. * * @hook init * @return void */ public function add_rewrite_rule() { add_rewrite_rule( '^llms\.txt$', 'index.php?llms_txt=1', 'top' ); add_rewrite_tag( '%llms_txt%', '1' ); } /** * Serve the llms.txt file if the endpoint is hit. * * @hook template_redirect * @return void */ public function maybe_serve_llms_txt() { if ( intval( get_query_var( 'llms_txt' ) ) !== 1 ) { return; } if ( substr( Url::get_current_url(), -1 ) === '/' ) { wp_safe_redirect( home_url( '/llms.txt' ) ); exit; } $this->output(); exit; } /** * Output the llms.txt file content in Markdown format. * * @action rank_math/llms_txt/before_output Fires before llms.txt output is sent. * @action rank_math/llms_txt/after_output Fires after llms.txt output is sent. * @filter rank_math/llms_txt/posts_query_args Filter WP_Query args for posts. * @filter rank_math/llms_txt/posts Filter post IDs to include. * @filter rank_math/llms_txt/terms Filter term IDs to include. * @filter rank_math/llms_txt/extra_content Filter extra content output. * * @return void */ public function output() { if ( headers_sent() ) { return; } header( 'Content-Type: text/plain; charset=utf-8' ); header( 'X-Robots-Tag: noindex, nofollow', true ); /** * Fires before the llms.txt output is sent to the browser. * * @since 1.0.250 */ $this->do_action( 'llms_txt/before_output' ); $limit = absint( Helper::get_settings( 'general.llms_limit', 100 ) ); $this->add_header_content(); $this->add_post_types_data( $limit ); $this->add_taxonomies_data( $limit ); $this->add_extra_content(); /** * Fires after the llms.txt output is sent to the browser. * * @since 1.0.250 */ $this->do_action( 'llms_txt/after_output' ); } /** * Adds header content to the llms.txt output. * * @return void */ private function add_header_content() { $site_title = Helper::get_settings( 'titles.knowledgegraph_name', get_bloginfo( 'name' ) ); $site_desc = Helper::get_settings( 'titles.organization_description', get_bloginfo( 'description' ) ); $site_title .= $site_desc ? ': ' . $site_desc : ''; $this->output_line( 'Generated by Rank Math SEO, this is an llms.txt file designed to help LLMs better understand and index this website.' ); $this->output_line( '' ); $this->output_line( '# ' . esc_html( $site_title ) ); if ( ! Helper::is_module_active( 'sitemap' ) ) { return; } $this->output_line( '' ); $sitemap_url = Router::get_base_url( Sitemap::get_sitemap_index_slug() . '.xml' ); $this->output_line( '## Sitemaps' ); $this->output_line( '[XML Sitemap](' . esc_url( $sitemap_url ) . '): Includes all crawlable and indexable pages.' ); // Add an extra blank line after the header content. $this->output_line( '' ); } /** * Adds post type data to the llms.txt output. * * @param int $limit The maximum number of posts to include per post type. * @return void */ private function add_post_types_data( $limit ) { $post_types = Helper::get_settings( 'general.llms_post_types', [] ); if ( empty( $post_types ) ) { return; } foreach ( $post_types as $post_type ) { $args = [ 'post_type' => $post_type, 'post_status' => 'publish', 'posts_per_page' => $limit, 'no_found_rows' => true, ]; /** * Filter the WP_Query arguments used to fetch posts for llms.txt. * * @since 1.0.250 * @param array $args The WP_Query arguments. * @return array Modified WP_Query arguments. */ $args = $this->do_filter( 'llms_txt/posts_query_args', $args ); $query = new \WP_Query( $args ); /** * Filter the list of post IDs to be included in llms.txt for a post type. * * @since 1.0.250 * @param array $posts List of posts. * @param array $args The WP_Query arguments. * @return array Modified list of post IDs. */ $posts = $this->do_filter( 'llms_txt/posts', $query->posts, $args ); if ( empty( $posts ) ) { continue; } $label = get_post_type_object( $post_type )->labels->name; $this->output_line( '## ' . esc_html( $label ) ); foreach ( $posts as $object ) { if ( ! Helper::is_post_indexable( $object ) ) { continue; } $title = get_the_title( $object ); $link = get_permalink( $object ); $desc = wp_strip_all_tags( Helper::replace_vars( '%excerpt%', $object ) ); $this->output_line( $desc ? '- [' . esc_html( $title ) . '](' . esc_url( $link ) . '): ' . esc_html( $desc ) : '- [' . esc_html( $title ) . '](' . esc_url( $link ) . ')' ); } $this->output_line( '' ); } } /** * Adds taxonomy data to the llms.txt output. * * @param int $limit The maximum number of terms to include per taxonomy. * @return void */ private function add_taxonomies_data( $limit ) { $taxonomies = Helper::get_settings( 'general.llms_taxonomies', [] ); if ( empty( $taxonomies ) ) { return; } foreach ( $taxonomies as $taxonomy ) { $tax_obj = get_taxonomy( $taxonomy ); if ( ! $tax_obj ) { continue; } $terms = get_terms( [ 'taxonomy' => $taxonomy, 'hide_empty' => true, 'number' => $limit, ] ); /** * Filter the list of terms to be included in llms.txt for a taxonomy. * * @since 1.0.250 * @param array $terms List of terms. * @param string $taxonomy Taxonomy name. * @return array Modified list of term IDs. */ $terms = $this->do_filter( 'llms_txt/terms', $terms, $taxonomy ); if ( empty( $terms ) ) { continue; } $label = $tax_obj->labels->name; $this->output_line( '## ' . esc_html( $label ) ); foreach ( $terms as $term ) { if ( $term && Helper::is_term_indexable( $term ) ) { $name = $term->name; $link = get_term_link( $term ); $this->output_line( '- [' . esc_html( $name ) . '](' . esc_url( $link ) . ')' ); } } $this->output_line( '' ); } } /** * Adds extra content to the end of the llms.txt output. * * @return void */ private function add_extra_content() { /** * Filter the extra content output at the end of llms.txt. * * @since 1.0.250 * @param string $extra The extra content string. * @return string Modified extra content. */ $extra = $this->do_filter( 'llms_txt/extra_content', Helper::get_settings( 'general.llms_extra_content', '' ) ); if ( ! empty( $extra ) ) { $this->output_line( esc_html( str_replace( "\n", "\n", $extra ) ) ); } } /** * Outputs a line with a newline character (\n). * * @param string $content The content to output. * @return void */ private function output_line( $content ) { echo esc_html( $content ) . "\n"; } }