File "Llms.php"
Full Path: /home/stylijtl/public_html/wp-content/plugins/all-in-one-seo-pack/app/Common/Llms/Llms.php
File size: 12.07 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace AIOSEO\Plugin\Common\Llms;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles the LLMS.txt generation.
*
* @since 4.8.4
*/
class Llms {
/**
* Site title
*
* since 4.8.4
*
* @var string
*/
protected $title;
/**
* Site description
*
* since 4.8.4
*
* @var string
*/
protected $description;
/**
* Site link
*
* since 4.8.4
*
* @var string
*/
protected $link;
/**
* Plugin version
*
* since 4.8.4
*
* @var string
*/
protected $version;
/**
* LLMS file recurrent action name.
*
* since 4.8.8
*
* @var string
*/
public $llmsTxtRecurrentAction = 'aioseo_generate_llms_txt';
/**
* LLMS file single action name.
*
* since 4.8.8
*
* @var string
*/
public $llmsTxtSingleAction = 'aioseo_generate_llms_txt_single';
/**
* Class constructor.
*
* @since 4.8.8
*
* @return void
*/
public function __construct() {
add_action( 'admin_init', [ $this, 'scheduleRecurrentGenerationForLlmsTxt' ] );
add_action( 'wp_insert_post', [ $this, 'scheduleSingleGenerationForLlmsTxt' ] );
add_action( 'edited_term', [ $this, 'scheduleSingleGenerationForLlmsTxt' ] );
add_action( $this->llmsTxtRecurrentAction, [ $this, 'generateLlmsTxt' ] );
add_action( $this->llmsTxtSingleAction, [ $this, 'generateLlmsTxt' ] );
}
/**
* Schedules the LLMS file generation.
*
* @since 4.8.8
*
* @return void
*/
public function scheduleRecurrentGenerationForLlmsTxt() {
if (
! aioseo()->options->sitemap->llms->enable ||
aioseo()->actionScheduler->isScheduled( $this->llmsTxtRecurrentAction )
) {
return;
}
aioseo()->actionScheduler->scheduleRecurrent( $this->llmsTxtRecurrentAction, 10, DAY_IN_SECONDS );
}
/**
* Schedules a single LLMS file generation.
*
* @since 4.8.8
*
* @return void
*/
public function scheduleSingleGenerationForLlmsTxt() {
if (
! aioseo()->options->sitemap->llms->enable ||
aioseo()->actionScheduler->isScheduled( $this->llmsTxtSingleAction )
) {
return;
}
aioseo()->actionScheduler->scheduleSingle( $this->llmsTxtSingleAction, 10 );
}
/**
* Sets the site info.
*
* @since 4.8.4
*
* @return void
*/
protected function setSiteInfo() {
$isMultisite = is_multisite();
// Check for LLMS custom title setting
$llmsTitle = aioseo()->options->sitemap->llms->advancedSettings->title;
if ( ! empty( $llmsTitle ) ) {
// Use LLMS title with hashtag tag replacement
$this->title = aioseo()->tags->replaceTags( $llmsTitle );
} else {
// Fallback to default site title
$this->title = $isMultisite
? get_blog_option( get_current_blog_id(), 'blogname' )
: get_bloginfo( 'name' );
$this->title = $this->title ?: aioseo()->meta->title->getHomePageTitle();
}
// Check for LLMS custom description setting
$llmsDescription = aioseo()->options->sitemap->llms->advancedSettings->description;
if ( ! empty( $llmsDescription ) ) {
// Use LLMS description with hashtag tag replacement
$this->description = aioseo()->tags->replaceTags( $llmsDescription );
} else {
// Fallback to default site description
$this->description = $isMultisite
? get_blog_option( get_current_blog_id(), 'blogdescription' )
: get_bloginfo( 'description' );
$this->description = $this->description ?: aioseo()->meta->description->getHomePageDescription();
}
$this->link = $isMultisite
? get_blog_option( get_current_blog_id(), 'siteurl' )
: home_url();
$this->version = aioseo()->helpers->getAioseoVersion();
}
/**
* Generates the LLMS.txt file.
*
* @since 4.8.4
*
* @return void
*/
public function generateLlmsTxt() {
if ( isset( aioseo()->options->sitemap->llms->enable ) && ! aioseo()->options->sitemap->llms->enable ) {
aioseo()->actionScheduler->unschedule( $this->llmsTxtSingleAction );
aioseo()->actionScheduler->unschedule( $this->llmsTxtRecurrentAction );
$this->deleteLlmsFile();
return;
}
$fs = aioseo()->core->fs;
$file = $this->getFilePath();
// Generate the full content
$this->setSiteInfo();
$content = $this->getHeader();
$content .= $this->getSiteDescription();
$content .= $this->getSitemapUrl();
$content .= $this->getContent();
// Add UTF-8 BOM to help browsers recognize the encoding
$content = "\xEF\xBB\xBF" . $content;
$fs->putContents( $file, $content );
}
/**
* Gets the header section of the llms.txt file.
*
* @since 4.8.4
*
* @return string
*/
protected function getHeader( $llmsFull = false ) {
$fileName = $llmsFull ? 'llms-full.txt' : 'llms.txt';
$introText = sprintf(
/* translators: 1 - The plugin name ("All in One SEO"), 2 - The version number */
esc_html__( 'Generated by %1$s v%2$s, this is an %3$s file, used by LLMs to index the site.', 'all-in-one-seo-pack' ),
esc_html( AIOSEO_PLUGIN_NAME ),
esc_html( aioseo()->version ),
esc_html( $fileName )
);
if ( $this->title ) {
$introText .= esc_html( "\n\n# {$this->title}\n\n" );
}
return $introText;
}
/**
* Gets the site description section of the llms.txt file.
*
* @since 4.8.4
*
* @return string
*/
protected function getSiteDescription() {
if ( $this->description ) {
return "{$this->description}\n\n";
}
return '';
}
/**
* Gets the sitemap link section of the llms.txt file.
*
* @since 4.8.4
*
* @return string
*/
protected function getSitemapUrl() {
if ( ! aioseo()->options->sitemap->general->enable ) {
return '';
}
$sitemapUrl = aioseo()->sitemap->helpers->getUrl( 'general' );
return "## Sitemaps\n\n- [XML Sitemap]({$sitemapUrl}): Contains all public & indexable URLs for this website.\n\n";
}
/**
* Gets the recent content section of the llms.txt file.
*
* @since 4.8.4
*
* @param bool $llmsFull Whether to include the llms-full.txt file.
* @return string The content of the llms.txt file.
*/
protected function getContent( $llmsFull = false ) {
// Get LLMS post types settings
$includeAllPostTypes = aioseo()->options->sitemap->llms->advancedSettings->postTypes->all;
$includedPostTypes = aioseo()->options->sitemap->llms->advancedSettings->postTypes->included;
$includeAllTaxonomies = aioseo()->options->sitemap->llms->advancedSettings->taxonomies->all;
$includedTaxonomies = aioseo()->options->sitemap->llms->advancedSettings->taxonomies->included;
// Determine which post types to include
if ( $includeAllPostTypes ) {
// Include all public post types except attachments
$postTypes = array_filter( aioseo()->helpers->getPublicPostTypes( true ), function( $type ) {
return 'attachment' !== $type;
} );
} else {
// Only include the specifically selected post types, but still exclude attachments
$postTypes = array_filter( $includedPostTypes, function( $type ) {
return 'attachment' !== $type;
} );
}
if ( $includeAllTaxonomies ) {
$taxonomies = aioseo()->helpers->getPublicTaxonomies( true );
} else {
$taxonomies = $includedTaxonomies;
}
$originalSitemapType = aioseo()->sitemap->type;
$originalLinksPerIndex = aioseo()->sitemap->linksPerIndex;
$originalIndexes = aioseo()->sitemap->indexes;
aioseo()->sitemap->type = 'llms';
aioseo()->sitemap->indexes = true;
aioseo()->sitemap->linksPerIndex = aioseo()->options->sitemap->llms->advancedSettings->linksPerPostTax
? aioseo()->options->sitemap->llms->advancedSettings->linksPerPostTax :
20;
$content = '';
foreach ( $postTypes as $postType ) {
$postTypeObject = get_post_type_object( $postType );
if ( ! $postTypeObject ) {
continue;
}
$posts = aioseo()->sitemap->query->posts( $postType );
if ( ! empty( $posts ) ) {
$content .= '## ' . $postTypeObject->labels->name . "\n\n";
foreach ( $posts as $postObject ) {
$post = get_post( $postObject->ID );
if ( ! is_a( $post, 'WP_Post' ) ) {
continue;
}
aioseo()->helpers->setWpQueryPost( $post );
$content .= $this->getPostContent( $post, $llmsFull );
aioseo()->helpers->restoreWpQuery();
}
$content .= "\n";
}
}
// Initialize sitemap settings again for terms
aioseo()->sitemap->type = 'llms';
aioseo()->sitemap->indexes = true;
aioseo()->sitemap->linksPerIndex = aioseo()->options->sitemap->llms->advancedSettings->linksPerPostTax
? aioseo()->options->sitemap->llms->advancedSettings->linksPerPostTax :
20;
// Get recent terms for each taxonomy using sitemap query
foreach ( $taxonomies as $taxonomy ) {
$taxonomyObject = get_taxonomy( $taxonomy );
if ( ! $taxonomyObject ) {
continue;
}
$terms = aioseo()->sitemap->query->terms( $taxonomy );
if ( ! empty( $terms ) ) {
$content .= '## ' . $taxonomyObject->labels->name . "\n\n";
foreach ( $terms as $termObject ) {
if ( is_object( $termObject ) && ! empty( $termObject->term_id ) ) {
$term = get_term( $termObject->term_id, $taxonomy );
if ( is_wp_error( $term ) ) {
continue;
}
aioseo()->helpers->setWpQueryTerm( $term, $taxonomy );
$content .= $this->getTermContent( $term, $taxonomy, $llmsFull );
aioseo()->helpers->restoreWpQuery();
}
}
$content .= "\n";
}
}
// Restore original sitemap settings
aioseo()->sitemap->type = $originalSitemapType;
aioseo()->sitemap->linksPerIndex = $originalLinksPerIndex;
aioseo()->sitemap->indexes = $originalIndexes;
return $content;
}
/**
* Gets the post content section of the llms.txt file.
*
* @since 4.8.8
*
* @param \WP_Post $post The post object.
* @param bool $llmsFull Whether to include the llms-full.txt file.
* @return string The content of the llms.txt file.
*/
protected function getPostContent( $post, $llmsFull = false ) { // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$title = apply_filters( 'aioseo_llms_post_title', $post->post_title, $post );
$content = '- [' . aioseo()->helpers->decodeHtmlEntities( $title ) . '](' . aioseo()->helpers->decodeUrl( get_permalink( $post ) ) . ')';
$description = aioseo()->meta->description->getPostDescription( $post );
$description = apply_filters( 'aioseo_llms_post_description', $description, $post );
if ( ! empty( $description ) ) {
$content .= ' - ' . aioseo()->helpers->decodeHtmlEntities( $description );
}
$content .= "\n";
return $content;
}
/**
* Gets the term content section of the llms.txt file.
*
* @since 4.9.3
*
* @param \WP_Term $term The term object.
* @param string $taxonomy The taxonomy name.
* @param bool $llmsFull Whether to include the llms-full.txt file.
* @return string The content of the llms.txt file.
*/
protected function getTermContent( $term, $taxonomy, $llmsFull = false ) { // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$title = apply_filters( 'aioseo_llms_term_title', $term->name, $term );
$content = '- [' . aioseo()->helpers->decodeHtmlEntities( $title ) . '](' . aioseo()->helpers->decodeUrl( get_term_link( $term, $taxonomy ) ) . ')';
$description = aioseo()->meta->description->getTermDescription( $term );
$description = apply_filters( 'aioseo_llms_term_description', $description, $term );
if ( ! empty( $description ) ) {
$content .= ' - ' . aioseo()->helpers->decodeHtmlEntities( $description );
}
$content .= "\n";
return $content;
}
/**
* Deletes the LLMS.txt file.
*
* @since 4.8.8
*
* @return void
*/
public function deleteLlmsFile() {
$fs = aioseo()->core->fs;
$file = $this->getFilePath();
if ( $fs->isWpfsValid() ) {
$fs->fs->delete( $file, false, 'f' );
}
}
/**
* Gets the file path for the llms.txt or llms-full.txt file.
*
* Uses `dirname( WP_CONTENT_DIR )` instead of `ABSPATH` to support non-standard
* WordPress installations where `ABSPATH` doesn't point to the web root.
*
* @since 4.9.5
*
* @param bool $full Whether to get the full version path.
* @return string The file path.
*/
public function getFilePath( $full = false ) {
$filename = $full ? 'llms-full.txt' : 'llms.txt';
return trailingslashit( dirname( WP_CONTENT_DIR ) ) . sanitize_file_name( $filename );
}
}