PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.2
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.2
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / integrations / watchers / indexable-permalink-watcher.php

indexable-permalink-watcher.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 18.2, at src/integrations/watchers/indexable-permalink-watcher.php

274 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Integrations\Watchers;
4
5 use Yoast\WP\SEO\Conditionals\Migrations_Conditional;
6 use Yoast\WP\SEO\Config\Indexing_Reasons;
7 use Yoast\WP\SEO\Helpers\Indexable_Helper;
8 use Yoast\WP\SEO\Helpers\Options_Helper;
9 use Yoast\WP\SEO\Helpers\Post_Type_Helper;
10 use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
11 use Yoast\WP\SEO\Integrations\Integration_Interface;
12
13 /**
14 * WordPress Permalink structure watcher.
15 *
16 * Handles updates to the permalink_structure for the Indexables table.
17 */
18 class Indexable_Permalink_Watcher implements Integration_Interface {
19
20 /**
21 * Represents the options helper.
22 *
23 * @var Options_Helper
24 */
25 protected $options_helper;
26
27 /**
28 * The taxonomy helper.
29 *
30 * @var Taxonomy_Helper
31 */
32 protected $taxonomy_helper;
33
34 /**
35 * The post type helper.
36 *
37 * @var Post_Type_Helper
38 */
39 private $post_type;
40
41 /**
42 * The indexable helper.
43 *
44 * @var Indexable_Helper
45 */
46 protected $indexable_helper;
47
48 /**
49 * Returns the conditionals based on which this loadable should be active.
50 *
51 * @return array
52 */
53 public static function get_conditionals() {
54 return [ Migrations_Conditional::class ];
55 }
56
57 /**
58 * Indexable_Permalink_Watcher constructor.
59 *
60 * @param Post_Type_Helper $post_type The post type helper.
61 * @param Options_Helper $options The options helper.
62 * @param Indexable_Helper $indexable The indexable helper.
63 * @param Taxonomy_Helper $taxonomy_helper The taxonomy helper.
64 */
65 public function __construct( Post_Type_Helper $post_type, Options_Helper $options, Indexable_Helper $indexable, Taxonomy_Helper $taxonomy_helper ) {
66 $this->post_type = $post_type;
67 $this->options_helper = $options;
68 $this->indexable_helper = $indexable;
69 $this->taxonomy_helper = $taxonomy_helper;
70
71 $this->schedule_cron();
72 }
73
74 /**
75 * Registers the hooks.
76 *
77 * @return void
78 */
79 public function register_hooks() {
80 \add_action( 'update_option_permalink_structure', [ $this, 'reset_permalinks' ] );
81 \add_action( 'update_option_category_base', [ $this, 'reset_permalinks_term' ], 10, 3 );
82 \add_action( 'update_option_tag_base', [ $this, 'reset_permalinks_term' ], 10, 3 );
83 \add_action( 'wpseo_permalink_structure_check', [ $this, 'force_reset_permalinks' ] );
84 \add_action( 'wpseo_deactivate', [ $this, 'unschedule_cron' ] );
85 }
86
87 /**
88 * Resets the permalinks for everything that is related to the permalink structure.
89 */
90 public function reset_permalinks() {
91
92 $post_types = $this->get_post_types();
93 foreach ( $post_types as $post_type ) {
94 $this->reset_permalinks_post_type( $post_type );
95 }
96
97 $taxonomies = $this->get_taxonomies_for_post_types( $post_types );
98 foreach ( $taxonomies as $taxonomy ) {
99 $this->indexable_helper->reset_permalink_indexables( 'term', $taxonomy );
100 }
101
102 $this->indexable_helper->reset_permalink_indexables( 'user' );
103 $this->indexable_helper->reset_permalink_indexables( 'date-archive' );
104 $this->indexable_helper->reset_permalink_indexables( 'system-page' );
105
106 // Always update `permalink_structure` in the wpseo option.
107 $this->options_helper->set( 'permalink_structure', \get_option( 'permalink_structure' ) );
108 }
109
110 /**
111 * Resets the permalink for the given post type.
112 *
113 * @param string $post_type The post type to reset.
114 */
115 public function reset_permalinks_post_type( $post_type ) {
116 $this->indexable_helper->reset_permalink_indexables( 'post', $post_type );
117 $this->indexable_helper->reset_permalink_indexables( 'post-type-archive', $post_type );
118 }
119
120 /**
121 * Resets the term indexables when the base has been changed.
122 *
123 * @param string $old Unused. The old option value.
124 * @param string $new Unused. The new option value.
125 * @param string $type The option name.
126 */
127 public function reset_permalinks_term( $old, $new, $type ) {
128 $subtype = $type;
129
130 $reason = Indexing_Reasons::REASON_PERMALINK_SETTINGS;
131
132 // When the subtype contains _base, just strip it.
133 if ( \strstr( $subtype, '_base' ) ) {
134 $subtype = \substr( $type, 0, -5 );
135 }
136
137 if ( $subtype === 'tag' ) {
138 $subtype = 'post_tag';
139 $reason = Indexing_Reasons::REASON_TAG_BASE_PREFIX;
140 }
141
142 if ( $subtype === 'category' ) {
143 $reason = Indexing_Reasons::REASON_CATEGORY_BASE_PREFIX;
144 }
145
146 $this->indexable_helper->reset_permalink_indexables( 'term', $subtype, $reason );
147 }
148
149 /**
150 * Resets the permalink indexables automatically, if necessary.
151 *
152 * @return bool Whether the reset request ran.
153 */
154 public function force_reset_permalinks() {
155 if ( \get_option( 'tag_base' ) !== $this->options_helper->get( 'tag_base_url' ) ) {
156 $this->reset_permalinks_term( null, null, 'tag_base' );
157 $this->options_helper->set( 'tag_base_url', \get_option( 'tag_base' ) );
158 }
159 if ( \get_option( 'category_base' ) !== $this->options_helper->get( 'category_base_url' ) ) {
160 $this->reset_permalinks_term( null, null, 'category_base' );
161 $this->options_helper->set( 'category_base_url', \get_option( 'category_base' ) );
162 }
163
164 if ( $this->should_reset_permalinks() ) {
165 $this->reset_permalinks();
166
167 return true;
168 }
169
170 $this->reset_altered_custom_taxonomies();
171
172 return true;
173 }
174
175 /**
176 * Checks whether the permalinks should be reset after `permalink_structure` has changed.
177 *
178 * @return bool Whether the permalinks should be reset.
179 */
180 public function should_reset_permalinks() {
181 return \get_option( 'permalink_structure' ) !== $this->options_helper->get( 'permalink_structure' );
182 }
183
184 /**
185 * Resets custom taxonomies if their slugs have changed.
186 *
187 * @return void
188 */
189 public function reset_altered_custom_taxonomies() {
190 $taxonomies = $this->taxonomy_helper->get_custom_taxonomies();
191 $custom_taxonomy_bases = $this->options_helper->get( 'custom_taxonomy_slugs', [] );
192 $new_taxonomy_bases = [];
193
194 foreach ( $taxonomies as $taxonomy ) {
195 $taxonomy_slug = $this->taxonomy_helper->get_taxonomy_slug( $taxonomy );
196
197 $new_taxonomy_bases[ $taxonomy ] = $taxonomy_slug;
198
199 if ( ! \array_key_exists( $taxonomy, $custom_taxonomy_bases ) ) {
200 continue;
201 }
202
203 if ( $taxonomy_slug !== $custom_taxonomy_bases[ $taxonomy ] ) {
204 $this->indexable_helper->reset_permalink_indexables( 'term', $taxonomy );
205 }
206 }
207
208 $this->options_helper->set( 'custom_taxonomy_slugs', $new_taxonomy_bases );
209 }
210
211 /**
212 * Retrieves a list with the public post types.
213 *
214 * @return array The post types.
215 */
216 protected function get_post_types() {
217 /**
218 * Filter: Gives the possibility to filter out post types.
219 *
220 * @param array $post_types The post type names.
221 *
222 * @return array The post types.
223 */
224 $post_types = \apply_filters( 'wpseo_post_types_reset_permalinks', $this->post_type->get_public_post_types() );
225
226 return $post_types;
227 }
228
229 /**
230 * Retrieves the taxonomies that belongs to the public post types.
231 *
232 * @param array $post_types The post types to get taxonomies for.
233 *
234 * @return array The retrieved taxonomies.
235 */
236 protected function get_taxonomies_for_post_types( $post_types ) {
237 $taxonomies = [];
238 foreach ( $post_types as $post_type ) {
239 $taxonomies[] = \get_object_taxonomies( $post_type, 'names' );
240 }
241
242 $taxonomies = \array_merge( [], ...$taxonomies );
243 $taxonomies = \array_unique( $taxonomies );
244
245 return $taxonomies;
246 }
247
248 /**
249 * Schedules the WP-Cron job to check the permalink_structure status.
250 *
251 * @return void
252 */
253 protected function schedule_cron() {
254 if ( \wp_next_scheduled( 'wpseo_permalink_structure_check' ) ) {
255 return;
256 }
257
258 \wp_schedule_event( \time(), 'daily', 'wpseo_permalink_structure_check' );
259 }
260
261 /**
262 * Unschedules the WP-Cron job to check the permalink_structure status.
263 *
264 * @return void
265 */
266 public function unschedule_cron() {
267 if ( ! \wp_next_scheduled( 'wpseo_permalink_structure_check' ) ) {
268 return;
269 }
270
271 \wp_clear_scheduled_hook( 'wpseo_permalink_structure_check' );
272 }
273 }
274