PluginProbe ʕ •ᴥ•ʔ
Hostinger Tools / 3.0.71
Hostinger Tools v3.0.71
3.0.71 3.0.70 3.0.69 3.0.68 3.0.67 3.0.66 1.8.1 1.8.2 1.8.3 1.9.1 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.4 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.2 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 3.0.0 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.24 3.0.25 3.0.26 3.0.27 3.0.28 3.0.29 3.0.3 3.0.30 3.0.31 3.0.32 3.0.33 3.0.34 3.0.35 3.0.36 3.0.37 3.0.38 3.0.39 3.0.4 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.0.46 3.0.47 3.0.48 3.0.49 3.0.5 3.0.50 3.0.51 3.0.52 3.0.53 3.0.54 3.0.55 3.0.56 3.0.57 3.0.58 3.0.59 3.0.6 3.0.60 3.0.61 3.0.62 3.0.65 3.0.7 3.0.8 3.0.9 trunk 1.8.0
hostinger / includes / LlmsTxtGenerator.php
hostinger / includes Last commit date
Admin 2 months ago Cli 2 weeks ago LlmsTxtGenerator 2 weeks ago Mcp 11 months ago Preview 1 year ago Rest 10 months ago Views 1 year ago Activator.php 1 year ago Bootstrap.php 9 months ago Cli.php 9 months ago ComingSoon.php 2 months ago Deactivator.php 1 year ago DefaultOptions.php 2 months ago Errors.php 1 year ago Helper.php 9 months ago Hooks.php 2 months ago Hostinger.php 2 months ago I18n.php 1 year ago LlmsTxtGenerator.php 1 year ago Loader.php 1 year ago Settings.php 1 year ago
LlmsTxtGenerator.php
189 lines
1 <?php
2
3 namespace Hostinger;
4
5 use Hostinger\Admin\PluginSettings;
6
7 defined( 'ABSPATH' ) || exit;
8
9 class LlmsTxtGenerator {
10
11 public const HOSTINGER_LLMSTXT_FILENAME = 'llms.txt';
12 public const HOSTINGER_LLMSTXT_SIGNATURE = '[comment]: # (Generated by Hostinger Tools Plugin)';
13
14 protected const HOSTINGER_LLMSTXT_SUPPORTED_POST_TYPES = array(
15 'post',
16 'page',
17 );
18 protected const UTF8_BOM = "\xEF\xBB\xBF";
19
20 protected PluginSettings $plugin_settings;
21
22
23 public function __construct( PluginSettings $plugin_settings ) {
24 $this->plugin_settings = $plugin_settings;
25 add_action( 'init', array( $this, 'init' ) );
26 }
27
28 public function init(): void {
29 if ( wp_doing_ajax() || wp_doing_cron() || ! current_user_can( 'manage_options' ) ) {
30 return;
31 }
32
33 $settings = $this->plugin_settings->get_plugin_settings();
34
35 if ( $settings->get_enable_llms_txt() && ! $this->llmstxt_file_exists() ) {
36 $this->generate();
37 }
38
39 $this->init_hooks();
40 }
41
42 public function on_settings_update( bool $is_enabled ): void {
43 if ( $is_enabled ) {
44 $this->generate();
45 } else {
46 $this->delete();
47 }
48 }
49
50 public function is_user_generated_file(): bool {
51 if ( ! $this->llmstxt_file_exists() ) {
52 return false;
53 }
54
55 global $wp_filesystem;
56 $this->init_wp_filesystem();
57 $content = $wp_filesystem->get_contents( $this->get_llmstxt_file_path() );
58
59 if ( $content === false ) {
60 return false;
61 }
62
63 return ! str_contains( $content, self::HOSTINGER_LLMSTXT_SIGNATURE );
64 }
65
66 public function on_post_status_change( string $new_status, string $old_status, \WP_Post $post ): void {
67 if ( ! $this->is_post_type_supported( $post->post_type ) ) {
68 return;
69 }
70
71 if ( $new_status === 'publish' || $old_status === 'publish' ) {
72 $this->generate();
73 }
74 }
75
76 public function on_blog_change( mixed $old_value, mixed $new_value ): void {
77 if ( $old_value !== $new_value ) {
78 $this->generate();
79 }
80 }
81
82 public function get_content(): string {
83 $content = self::UTF8_BOM;
84 $content .= $this->inject_title();
85 $content .= $this->inject_site_description();
86 $content .= $this->inject_items( $this->get_by_post_type( 'post' ), 'Posts' );
87 $content .= $this->inject_items( $this->get_by_post_type( 'page' ), 'Pages' );
88 $content .= $this->inject_signature();
89
90 return $content;
91 }
92
93 public function init_hooks(): void {
94 add_action( 'transition_post_status', array( $this, 'on_post_status_change' ), 10, 3 );
95 add_action( 'hostinger_tools_setting_enable_llms_txt_update', array( $this, 'on_settings_update' ) );
96 add_action( 'update_option_blogname', array( $this, 'on_blog_change' ), 10, 2 );
97 add_action( 'update_option_blogdescription', array( $this, 'on_blog_change' ), 10, 2 );
98 }
99
100 protected function generate(): void {
101 if ( $this->is_user_generated_file() ) {
102 return;
103 }
104
105 global $wp_filesystem;
106 $this->init_wp_filesystem();
107 $wp_filesystem->put_contents( $this->get_llmstxt_file_path(), $this->get_content() );
108 }
109
110 protected function delete(): void {
111 if ( $this->llmstxt_file_exists() && ! $this->is_user_generated_file() ) {
112 global $wp_filesystem;
113 $this->init_wp_filesystem();
114 $wp_filesystem->delete( $this->get_llmstxt_file_path() );
115 }
116 }
117
118 protected function get_llmstxt_file_path(): string {
119 return ABSPATH . self::HOSTINGER_LLMSTXT_FILENAME;
120 }
121
122 protected function llmstxt_file_exists(): bool {
123 return file_exists( $this->get_llmstxt_file_path() );
124 }
125
126 protected function is_post_type_supported( string $post_type ): bool {
127 return in_array( $post_type, self::HOSTINGER_LLMSTXT_SUPPORTED_POST_TYPES, true );
128 }
129
130 protected function get_by_post_type( string $post_type, int $limit = 100 ): array {
131 $args = array(
132 'post_type' => $post_type,
133 'post_status' => 'publish',
134 'fields' => 'ids',
135 'posts_per_page' => apply_filters( 'hostinger_llmstext_item_limit', $limit, $post_type ),
136 );
137
138 return get_posts( $args );
139 }
140
141 protected function inject_site_description(): string {
142 $description = get_bloginfo( 'description' );
143 return $description ? "> $description\n\n" : '';
144 }
145
146 protected function inject_title(): string {
147 $title = get_bloginfo( 'name' ) ? get_bloginfo( 'name' ) : site_url();
148 return "# $title\n\n";
149 }
150
151 protected function inject_signature(): string {
152 return "\n\n" . self::HOSTINGER_LLMSTXT_SIGNATURE;
153 }
154
155 protected function inject_items( array $items, string $title ): string {
156 if ( empty( $items ) ) {
157 return '';
158 }
159
160 $content = "\n## $title\n\n";
161
162 foreach ( $items as $item ) {
163 $post = get_post( $item );
164 $title = $post->post_title;
165 $permalink = get_permalink( $post );
166 $excerpt = $this->prepare_excerpt( $post );
167
168 $content .= "- [$title]($permalink)";
169 if ( $excerpt ) {
170 $content .= ": $excerpt";
171 }
172
173 $content .= "\n";
174 }
175
176 return $content;
177 }
178
179 protected function prepare_excerpt( \WP_Post $item ): string {
180 return html_entity_decode( wp_trim_excerpt( $item->post_excerpt, $item ) );
181 }
182
183 protected function init_wp_filesystem() {
184 global $wp_filesystem;
185 require_once ABSPATH . '/wp-admin/includes/file.php';
186 WP_Filesystem();
187 }
188 }
189