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

249 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 * 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 an 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 /* translators: %1$s expands to the translated name of the post type. */
65 $first_sentence = sprintf( __( 'You just trashed a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) );
66 $message = $this->get_message( $first_sentence );
67
68 $this->add_notification( $message );
69 }
70
71 /**
72 * Shows an message when a post is about to get trashed.
73 *
74 * @param int $post_id The current post ID.
75 *
76 * @return void
77 */
78 public function detect_post_delete( $post_id ) {
79 if ( ! $this->is_post_viewable( $post_id ) ) {
80 return;
81 }
82
83 /* translators: %1$s expands to the translated name of the post type. */
84 $first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) );
85 $message = $this->get_message( $first_sentence );
86
87 $this->add_notification( $message );
88 }
89
90 /**
91 * Shows a message when a term is about to get deleted.
92 *
93 * @param int $term_id The term ID that will be deleted.
94 *
95 * @return void
96 */
97 public function detect_term_delete( $term_id ) {
98 if ( ! $this->is_term_viewable( $term_id ) ) {
99 return;
100 }
101
102 $first_sentence = sprintf(
103 /* translators: 1: term label */
104 __( 'You just deleted a %1$s.', 'wordpress-seo' ),
105 $this->get_taxonomy_label_for_term( $term_id )
106 );
107
108 $message = $this->get_message( $first_sentence );
109
110 $this->add_notification( $message );
111 }
112
113 /**
114 * Checks if the post is viewable.
115 *
116 * @param string $post_id The post id to check.
117 *
118 * @return bool Whether the post is viewable or not.
119 */
120 protected function is_post_viewable( $post_id ) {
121 $post_type = get_post_type( $post_id );
122 if ( ! WPSEO_Post_Type::is_post_type_accessible( $post_type ) ) {
123 return false;
124 }
125
126 $post_status = get_post_status( $post_id );
127 if ( ! $this->check_visible_post_status( $post_status ) ) {
128 return false;
129 }
130
131 return true;
132 }
133
134 /**
135 * Checks if the term is viewable.
136 *
137 * @param string $term_id The term ID to check.
138 *
139 * @return bool Whether the term is viewable or not.
140 */
141 protected function is_term_viewable( $term_id ) {
142 $term = get_term( $term_id );
143
144 if ( ! $term || is_wp_error( $term ) ) {
145 return false;
146 }
147
148 $taxonomy = get_taxonomy( $term->taxonomy );
149 if ( ! $taxonomy ) {
150 return false;
151 }
152
153 return $taxonomy->publicly_queryable || $taxonomy->public;
154 }
155
156 /**
157 * Gets the taxonomy label to use for a term.
158 *
159 * @param int $term_id The term ID.
160 *
161 * @return string The taxonomy's singular label.
162 */
163 protected function get_taxonomy_label_for_term( $term_id ) {
164 $term = get_term( $term_id );
165 $taxonomy = get_taxonomy( $term->taxonomy );
166
167 return $taxonomy->labels->singular_name;
168 }
169
170 /**
171 * Retrieves the singular post type label.
172 *
173 * @param string $post_type Post type to retrieve label from.
174 *
175 * @return string The singular post type name.
176 */
177 protected function get_post_type_label( $post_type ) {
178 $post_type_object = get_post_type_object( $post_type );
179
180 // If the post type of this post wasn't registered default back to post.
181 if ( $post_type_object === null ) {
182 $post_type_object = get_post_type_object( 'post' );
183 }
184
185 return $post_type_object->labels->singular_name;
186 }
187
188 /**
189 * Checks whether the given post status is visible or not.
190 *
191 * @param string $post_status The post status to check.
192 *
193 * @return bool Whether or not the post is visible.
194 */
195 protected function check_visible_post_status( $post_status ) {
196 $visible_post_statuses = [
197 'publish',
198 'static',
199 'private',
200 ];
201
202 return in_array( $post_status, $visible_post_statuses, true );
203 }
204
205 /**
206 * Returns the message around changed URLs.
207 *
208 * @param string $first_sentence The first sentence of the notification.
209 *
210 * @return string The full notification.
211 */
212 protected function get_message( $first_sentence ) {
213 return '<h2>' . __( 'Make sure you don\'t miss out on traffic!', 'wordpress-seo' ) . '</h2>'
214 . '<p>'
215 . $first_sentence
216 . ' ' . __( 'Search engines and other websites can still send traffic to your deleted post.', 'wordpress-seo' )
217 . ' ' . __( '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' )
218 /* translators: %s expands to Yoast SEO Premium */
219 . ' ' . sprintf( __( 'With %s, you can easily create such redirects.', 'wordpress-seo' ), 'Yoast SEO Premium' )
220 . '</p>'
221 . '<p><a class="yoast-button-upsell" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/1d0' ) . '" target="_blank">'
222 /* translators: %s expands to Yoast SEO Premium */
223 . sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' )
224 . '<span class="screen-reader-text">' . __( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>'
225 . '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>'
226 . '</a></p>';
227 }
228
229 /**
230 * Adds a notification to be shown on the next page request since posts are updated in an ajax request.
231 *
232 * @param string $message The message to add to the notification.
233 *
234 * @return void
235 */
236 protected function add_notification( $message ) {
237 $notification = new Yoast_Notification(
238 $message,
239 [
240 'type' => 'notice-warning is-dismissible',
241 'yoast_branding' => true,
242 ]
243 );
244
245 $notification_center = Yoast_Notification_Center::get();
246 $notification_center->add_notification( $notification );
247 }
248 }
249