PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
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 / admin / watchers / class-slug-change-watcher.php

class-slug-change-watcher.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI trunk, at admin/watchers/class-slug-change-watcher.php

255 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPSEO plugin file.
4 *
5 * @package WPSEO\Admin\Watchers
6 */
7
8 /**
9 * Class WPSEO_Slug_Change_Watcher.
10 */
11 class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
12
13 /**
14 * Registers all hooks to WordPress.
15 *
16 * @return void
17 */
18 public function register_hooks() {
19 // If the current plugin is Yoast SEO Premium, stop registering.
20 if ( YoastSEO()->helpers->product->is_premium() ) {
21 return;
22 }
23
24 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
25
26 // Detect a post trash.
27 add_action( 'wp_trash_post', [ $this, 'detect_post_trash' ] );
28
29 // Detect a post delete.
30 add_action( 'before_delete_post', [ $this, 'detect_post_delete' ] );
31
32 // Detects deletion of a term.
33 add_action( 'delete_term_taxonomy', [ $this, 'detect_term_delete' ] );
34 }
35
36 /**
37 * Enqueues the quick edit handler.
38 *
39 * @return void
40 */
41 public function enqueue_assets() {
42 global $pagenow;
43
44 if ( ! in_array( $pagenow, [ 'edit.php', 'edit-tags.php' ], true ) ) {
45 return;
46 }
47
48 $asset_manager = new WPSEO_Admin_Asset_Manager();
49 $asset_manager->enqueue_script( 'quick-edit-handler' );
50 }
51
52 /**
53 * Shows a message when a post is about to get trashed.
54 *
55 * @param int $post_id The current post ID.
56 *
57 * @return void
58 */
59 public function detect_post_trash( $post_id ) {
60 if ( ! $this->is_post_viewable( $post_id ) ) {
61 return;
62 }
63
64 $post_label = $this->get_post_type_label( get_post_type( $post_id ) );
65
66 /* translators: %1$s expands to the translated name of the post type. */
67 $first_sentence = sprintf( __( 'You just trashed a %1$s.', 'wordpress-seo' ), $post_label );
68 $second_sentence = __( 'Search engines and other websites can still send traffic to your trashed content.', 'wordpress-seo' );
69 $message = $this->get_message( $first_sentence, $second_sentence );
70
71 $this->add_notification( $message );
72 }
73
74 /**
75 * Shows a message when a post is about to get trashed.
76 *
77 * @param int $post_id The current post ID.
78 *
79 * @return void
80 */
81 public function detect_post_delete( $post_id ) {
82 if ( ! $this->is_post_viewable( $post_id ) ) {
83 return;
84 }
85
86 $post_label = $this->get_post_type_label( get_post_type( $post_id ) );
87
88 /* translators: %1$s expands to the translated name of the post type. */
89 $first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $post_label );
90 $second_sentence = __( 'Search engines and other websites can still send traffic to your deleted content.', 'wordpress-seo' );
91 $message = $this->get_message( $first_sentence, $second_sentence );
92
93 $this->add_notification( $message );
94 }
95
96 /**
97 * Shows a message when a term is about to get deleted.
98 *
99 * @param int $term_taxonomy_id The term taxonomy ID that will be deleted.
100 *
101 * @return void
102 */
103 public function detect_term_delete( $term_taxonomy_id ) {
104 if ( ! $this->is_term_viewable( $term_taxonomy_id ) ) {
105 return;
106 }
107
108 $term = get_term_by( 'term_taxonomy_id', (int) $term_taxonomy_id );
109 $term_label = $this->get_taxonomy_label_for_term( $term->term_id );
110
111 /* translators: %1$s expands to the translated name of the term. */
112 $first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $term_label );
113 $second_sentence = __( 'Search engines and other websites can still send traffic to your deleted content.', 'wordpress-seo' );
114 $message = $this->get_message( $first_sentence, $second_sentence );
115
116 $this->add_notification( $message );
117 }
118
119 /**
120 * Checks if the post is viewable.
121 *
122 * @param string $post_id The post id to check.
123 *
124 * @return bool Whether the post is viewable or not.
125 */
126 protected function is_post_viewable( $post_id ) {
127 $post_type = get_post_type( $post_id );
128 if ( ! WPSEO_Post_Type::is_post_type_accessible( $post_type ) ) {
129 return false;
130 }
131
132 $post_status = get_post_status( $post_id );
133 if ( ! $this->check_visible_post_status( $post_status ) ) {
134 return false;
135 }
136
137 return true;
138 }
139
140 /**
141 * Checks if the term is viewable.
142 *
143 * @param int $term_taxonomy_id The term taxonomy ID to check.
144 *
145 * @return bool Whether the term is viewable or not.
146 */
147 protected function is_term_viewable( $term_taxonomy_id ) {
148 $term = get_term_by( 'term_taxonomy_id', (int) $term_taxonomy_id );
149
150 if ( ! $term || is_wp_error( $term ) ) {
151 return false;
152 }
153
154 $taxonomy = get_taxonomy( $term->taxonomy );
155 if ( ! $taxonomy ) {
156 return false;
157 }
158
159 return $taxonomy->publicly_queryable || $taxonomy->public;
160 }
161
162 /**
163 * Gets the taxonomy label to use for a term.
164 *
165 * @param int $term_id The term ID.
166 *
167 * @return string The taxonomy's singular label.
168 */
169 protected function get_taxonomy_label_for_term( $term_id ) {
170 $term = get_term( $term_id );
171 $taxonomy = get_taxonomy( $term->taxonomy );
172
173 return $taxonomy->labels->singular_name;
174 }
175
176 /**
177 * Retrieves the singular post type label.
178 *
179 * @param string $post_type Post type to retrieve label from.
180 *
181 * @return string The singular post type name.
182 */
183 protected function get_post_type_label( $post_type ) {
184 $post_type_object = get_post_type_object( $post_type );
185
186 // If the post type of this post wasn't registered default back to post.
187 $post_type_object ??= get_post_type_object( 'post' );
188
189 return $post_type_object->labels->singular_name;
190 }
191
192 /**
193 * Checks whether the given post status is visible or not.
194 *
195 * @param string $post_status The post status to check.
196 *
197 * @return bool Whether or not the post is visible.
198 */
199 protected function check_visible_post_status( $post_status ) {
200 $visible_post_statuses = [
201 'publish',
202 'static',
203 'private',
204 ];
205
206 return in_array( $post_status, $visible_post_statuses, true );
207 }
208
209 /**
210 * Returns the message around changed URLs.
211 *
212 * @param string $first_sentence The first sentence of the notification.
213 * @param string $second_sentence The second sentence of the notification.
214 *
215 * @return string The full notification.
216 */
217 protected function get_message( $first_sentence, $second_sentence ) {
218 return '<h2>' . __( 'Make sure you don\'t miss out on traffic!', 'wordpress-seo' ) . '</h2>'
219 . '<p>'
220 . $first_sentence
221 . ' ' . $second_sentence
222 . ' ' . __( 'You should create a redirect to ensure your visitors do not get a 404 error when they click on the no longer working URL.', 'wordpress-seo' )
223 /* translators: %s expands to Yoast SEO Premium */
224 . ' ' . sprintf( __( 'With %s, you can easily create such redirects.', 'wordpress-seo' ), 'Yoast SEO Premium' )
225 . '</p>'
226 . '<p><a class="yoast-button-upsell" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/1d0' ) . '" target="_blank">'
227 /* translators: %s expands to Yoast SEO Premium */
228 . sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' )
229 /* translators: Hidden accessibility text. */
230 . '<span class="screen-reader-text">' . __( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>'
231 . '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>'
232 . '</a></p>';
233 }
234
235 /**
236 * Adds a notification to be shown on the next page request since posts are updated in an ajax request.
237 *
238 * @param string $message The message to add to the notification.
239 *
240 * @return void
241 */
242 protected function add_notification( $message ) {
243 $notification = new Yoast_Notification(
244 $message,
245 [
246 'type' => 'notice-warning is-dismissible',
247 'yoast_branding' => true,
248 ],
249 );
250
251 $notification_center = Yoast_Notification_Center::get();
252 $notification_center->add_notification( $notification );
253 }
254 }
255