PluginProbe
Hostinger Tools / 3.0.79
Hostinger Tools v3.0.79
3.0.79 3.0.78 3.0.77 3.0.76 3.0.75 3.0.74 3.0.73 3.0.72 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 All 110 releases
hostinger / includes / LlmsTxtGenerator / LlmsTxtGenerator.php

LlmsTxtGenerator.php in Hostinger Tools 3.0.79, at includes/LlmsTxtGenerator/LlmsTxtGenerator.php

201 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Hostinger\LlmsTxtGenerator;
4
5 use Hostinger\Admin\Jobs\LlmsTxtInjectContentJob;
6 use Hostinger\Admin\PluginSettings;
7 use Hostinger\Helper;
8
9 defined( 'ABSPATH' ) || exit;
10
11 class LlmsTxtGenerator {
12
13 public const HOSTINGER_LLMSTXT_SIGNATURE = '[comment]: # (Generated by Hostinger Tools Plugin)';
14 public const HOSTINGER_LLMSTXT_GENERATED_VERSION = 'hostinger_llmstxt_generated_version';
15 public const HOSTINGER_LLMSTXT_SUPPORTED_POST_TYPES = array(
16 'post' => 'Posts',
17 'page' => 'Pages',
18 'product' => 'Products',
19 );
20
21 /**
22 * Activation and deactivation hooks appears too early,
23 * so the plugin status is not available yet.
24 *
25 * That's why we use a flag this->woocommerce_status to know the plugin status.
26 *
27 * @var string|null
28 */
29 protected ?string $woocommerce_status = null;
30 protected PluginSettings $plugin_settings;
31 protected LlmsTxtFileHelper $file_helper;
32 protected LlmsTxtParser $parser;
33
34 public function __construct( PluginSettings $plugin_settings, LlmsTxtFileHelper $llmstxt_file_helper, LlmsTxtParser $llms_txt_parser ) {
35 $this->plugin_settings = $plugin_settings;
36 $this->file_helper = $llmstxt_file_helper;
37 $this->parser = $llms_txt_parser;
38 add_action( 'init', array( $this, 'init' ) );
39 }
40
41 public function on_woocommerce_activation(): void {
42 $this->woocommerce_status = 'active';
43 $this->generate();
44 }
45
46 public function on_woocommerce_deactivation(): void {
47 $this->woocommerce_status = 'inactive';
48 $this->generate();
49 }
50
51 public function init(): void {
52 $this->init_hooks();
53
54 if ( wp_doing_ajax() || wp_doing_cron() || ! current_user_can( 'manage_options' ) ) {
55 return;
56 }
57
58 $settings = $this->plugin_settings->get_plugin_settings();
59
60 if ( $settings->get_enable_llms_txt() && ! $this->file_helper->llmstxt_file_exists() ) {
61 $this->generate();
62 }
63 }
64
65 public function maybe_regenerate_after_update(): void {
66 if ( wp_doing_ajax() || wp_doing_cron() || ! current_user_can( 'manage_options' ) ) {
67 return;
68 }
69
70 if ( $this->has_generated_current_version() ) {
71 return;
72 }
73
74 $this->record_generated_version();
75 $this->generate();
76 }
77
78 public function on_settings_update( bool $is_enabled ): void {
79 if ( $is_enabled ) {
80 $this->generate();
81 } else {
82 $this->delete();
83 }
84 }
85
86 public function on_post_status_change( string $new_status, string $old_status, \WP_Post $post ): void {
87 if ( ! $this->is_post_type_supported( $post->post_type ) ) {
88 return;
89 }
90
91 if ( $new_status === 'publish' || $old_status === 'publish' ) {
92 $this->generate();
93 }
94 }
95
96 public function on_blog_change( mixed $old_value, mixed $new_value ): void {
97 if ( $old_value !== $new_value ) {
98 $this->generate();
99 }
100 }
101
102 public function get_content(): string {
103 $content = $this->parser->inject_title();
104 $content .= $this->parser->inject_site_description();
105 $content .= $this->parser->inject_items( $this->parser->get_by_post_type( 'post' ), 'Posts' );
106 $content .= $this->parser->inject_items( $this->parser->get_by_post_type( 'page' ), 'Pages' );
107 $content .= $this->maybe_inject_woocommerce_products();
108 $content .= $this->maybe_inject_optional_entries();
109 $content .= $this->parser->inject_signature();
110
111 return $content;
112 }
113
114 public function init_hooks(): void {
115 add_action( 'transition_post_status', array( $this, 'on_post_status_change' ), 10, 3 );
116 add_action( 'hostinger_tools_settings_saved', array( $this, 'on_settings_saved' ) );
117 add_action( 'update_option_blogname', array( $this, 'on_blog_change' ), 10, 2 );
118 add_action( 'update_option_blogdescription', array( $this, 'on_blog_change' ), 10, 2 );
119 add_action( 'activate_woocommerce/woocommerce.php', array( $this, 'on_woocommerce_activation' ) );
120 add_action( 'deactivate_woocommerce/woocommerce.php', array( $this, 'on_woocommerce_deactivation' ) );
121 }
122
123 public function on_settings_saved( array $settings ): void {
124 if ( $settings['enable_llms_txt'] ) {
125 $this->generate();
126 } else {
127 $this->delete();
128 }
129 }
130
131 public function generate(): void {
132 $settings = $this->plugin_settings->get_plugin_settings();
133 if ( ! $settings->get_enable_llms_txt() ) {
134 return;
135 }
136
137 if ( $this->file_helper->is_user_generated_file() ) {
138 return;
139 }
140
141 $this->file_helper->create( $this->get_content() );
142
143 $this->record_generated_version();
144
145 do_action( LlmsTxtInjectContentJob::JOB_NAME, array( 'post_type' => 'post' ) );
146 do_action( LlmsTxtInjectContentJob::JOB_NAME, array( 'post_type' => 'page' ) );
147
148 if ( $this->is_woocommerce_active() ) {
149 do_action( LlmsTxtInjectContentJob::JOB_NAME, array( 'post_type' => 'product' ) );
150 }
151 }
152
153 protected function delete(): void {
154 $this->file_helper->delete();
155 }
156
157 protected function has_generated_current_version(): bool {
158 return get_option( self::HOSTINGER_LLMSTXT_GENERATED_VERSION ) === HOSTINGER_WORDPRESS_PLUGIN_VERSION;
159 }
160
161 protected function record_generated_version(): void {
162 update_option( self::HOSTINGER_LLMSTXT_GENERATED_VERSION, HOSTINGER_WORDPRESS_PLUGIN_VERSION );
163 }
164
165 protected function is_post_type_supported( string $post_type ): bool {
166 return array_key_exists( $post_type, self::HOSTINGER_LLMSTXT_SUPPORTED_POST_TYPES );
167 }
168
169 protected function is_woocommerce_active(): bool {
170 return ( is_null( $this->woocommerce_status ) && Helper::is_plugin_active( 'woocommerce/woocommerce' ) ) || $this->woocommerce_status === 'active';
171 }
172
173 protected function maybe_inject_woocommerce_products(): string {
174 if ( ! $this->is_woocommerce_active() ) {
175 return '';
176 }
177
178 return $this->parser->inject_items( $this->parser->get_by_post_type( 'product' ), 'Products' );
179 }
180
181 protected function maybe_inject_optional_entries(): string {
182 $entries = array();
183 $mcp_entry = $this->maybe_inject_mcp_agent_entry();
184
185 if ( $mcp_entry ) {
186 $entries[] = $mcp_entry;
187 }
188
189 return $this->parser->inject_optional_entries( $entries );
190 }
191
192 protected function maybe_inject_mcp_agent_entry(): string {
193 $settings = $this->plugin_settings->get_plugin_settings();
194 if ( ! $settings->get_optin_mcp() ) {
195 return '';
196 }
197
198 return $this->parser->inject_mcp_agent_entry();
199 }
200 }
201