PluginProbe ʕ •ᴥ•ʔ
Rank Math SEO – AI SEO Tools to Dominate SEO Rankings / 1.0.271.1
Rank Math SEO – AI SEO Tools to Dominate SEO Rankings v1.0.271.1
1.0.271 1.0.271.1 1.0.270 1.0.269 trunk 1.0.216 1.0.217 1.0.218 1.0.219 1.0.220 1.0.221 1.0.222 1.0.223 1.0.224 1.0.225 1.0.226 1.0.227 1.0.227.1 1.0.228 1.0.229 1.0.230 1.0.231 1.0.232 1.0.233 1.0.234 1.0.234.1 1.0.235 1.0.236 1.0.237 1.0.238 1.0.239 1.0.240 1.0.241 1.0.242 1.0.243 1.0.244 1.0.245 1.0.246 1.0.247 1.0.248 1.0.249 1.0.250 1.0.251 1.0.251.1 1.0.252 1.0.252.1 1.0.253 1.0.254 1.0.255 1.0.256 1.0.257 1.0.258 1.0.259 1.0.259.1 1.0.260 1.0.261 1.0.262 1.0.263 1.0.264 1.0.264.1 1.0.265 1.0.266 1.0.266.1 1.0.267 1.0.268
seo-by-rank-math / includes / class-rewrite.php
seo-by-rank-math / includes Last commit date
3rdparty 6 days ago abilities 6 days ago admin 6 days ago cli 5 years ago frontend 2 weeks ago helpers 2 weeks ago metaboxes 2 years ago module 2 weeks ago modules 6 days ago opengraph 2 weeks ago replace-variables 2 weeks ago rest 6 days ago settings 2 weeks ago traits 2 weeks ago updates 2 weeks ago class-auto-updater.php 5 years ago class-cmb2.php 2 weeks ago class-common.php 5 months ago class-compatibility.php 1 year ago class-data-encryption.php 5 months ago class-defaults.php 6 years ago class-frontend-seo-score.php 2 weeks ago class-helper.php 10 months ago class-installer.php 2 weeks ago class-json-manager.php 1 year ago class-kb.php 7 months ago class-metadata.php 2 months ago class-post.php 1 year ago class-rewrite.php 5 months ago class-settings.php 1 year ago class-term.php 1 year ago class-thumbnail-overlay.php 1 year ago class-tracking.php 6 days ago class-update-email.php 2 weeks ago class-updates.php 3 months ago class-user.php 8 months ago index.php 7 years ago interface-runner.php 7 years ago template-tags.php 1 year ago
class-rewrite.php
337 lines
1 <?php
2 /**
3 * This class handles the category and author rewrites.
4 *
5 * @since 0.9.0
6 * @package RankMath
7 * @subpackage RankMath\Core
8 * @author Rank Math <support@rankmath.com>
9 *
10 * @copyright Copyright (C) 2008-2019, Yoast BV
11 * The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
12 */
13
14 namespace RankMath;
15
16 use RankMath\Traits\Hooker;
17 use RankMath\Helpers\Sitepress;
18 use RankMath\Helpers\DB as DB_Helper;
19
20 defined( 'ABSPATH' ) || exit;
21
22 /**
23 * Rewrite class.
24 */
25 class Rewrite {
26
27 use Hooker;
28
29 /**
30 * The Constructor.
31 */
32 public function __construct() {
33
34 if ( Helper::get_settings( 'general.strip_category_base' ) ) {
35 $this->filter( 'query_vars', 'query_vars' );
36 $this->filter( 'request', 'request' );
37 $this->filter( 'category_rewrite_rules', 'category_rewrite_rules' );
38 $this->filter( 'term_link', 'no_category_base', 10, 3 );
39
40 add_action( 'created_category', 'RankMath\\Helper::schedule_flush_rewrite' );
41 add_action( 'delete_category', 'RankMath\\Helper::schedule_flush_rewrite' );
42 add_action( 'edited_category', 'RankMath\\Helper::schedule_flush_rewrite' );
43 }
44
45 if ( ! Helper::get_settings( 'titles.disable_author_archives' ) ) {
46 if ( ! empty( Helper::get_settings( 'titles.url_author_base' ) ) ) {
47 add_action( 'init', 'RankMath\\Rewrite::change_author_base', 4 );
48 }
49
50 $this->filter( 'author_link', 'author_link', 10, 3 );
51 $this->filter( 'request', 'author_request' );
52 }
53 }
54
55 /**
56 * Change the URL to the author's page.
57 *
58 * @param string $link The URL to the author's page.
59 * @param int $author_id The author's ID.
60 * @param string $author_nicename The author's nice name.
61 * @return string
62 */
63 public function author_link( $link, $author_id, $author_nicename ) {
64 $custom_url = get_user_meta( $author_id, 'rank_math_permalink', true );
65 if ( $custom_url ) {
66 $link = str_replace( $author_nicename, $custom_url, $link );
67 }
68
69 return $link;
70 }
71
72 /**
73 * Redirect the old user permalink to the new one.
74 *
75 * @param array $query_vars Query vars to check for author_name var.
76 *
77 * @return array
78 */
79 public function author_request( $query_vars ) {
80 global $wpdb;
81
82 if ( ! array_key_exists( 'author_name', $query_vars ) ) {
83 return $query_vars;
84 }
85
86 $author_id = DB_Helper::get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key='rank_math_permalink' AND meta_value = %s", $query_vars['author_name'] ) );
87 if ( $author_id ) {
88 $query_vars['author'] = $author_id;
89 unset( $query_vars['author_name'] );
90 }
91
92 return $query_vars;
93 }
94
95 /**
96 * Remove the rewrite rules.
97 */
98 public function remove_rules() {
99 $this->remove_filter( 'query_vars', 'query_vars' );
100 $this->remove_filter( 'request', 'request' );
101 $this->remove_filter( 'category_rewrite_rules', 'category_rewrite_rules' );
102 $this->remove_filter( 'term_link', 'no_category_base', 10 );
103
104 remove_action( 'init', 'RankMath\\Rewrite::change_author_base', 4 );
105 }
106
107 /**
108 * Change the base for author permalinks.
109 */
110 public static function change_author_base() {
111 global $wp_rewrite;
112
113 /**
114 * Filter: Change the author base.
115 *
116 * @param string $base The author base.
117 */
118 $base = apply_filters( 'rank_math/author_base', sanitize_title_with_dashes( Helper::get_settings( 'titles.url_author_base' ), '', 'save' ) );
119 if ( empty( $base ) ) {
120 return;
121 }
122
123 $wp_rewrite->author_base = $base;
124 $wp_rewrite->author_structure = '/' . $wp_rewrite->author_base . '/%author%';
125 }
126
127 /**
128 * Add the redirect var to the query vars if the "strip category bases" option is enabled.
129 *
130 * @param array $query_vars Query vars to filter.
131 *
132 * @return array
133 */
134 public function query_vars( $query_vars ) {
135 $query_vars[] = 'rank_math_category_redirect';
136
137 return $query_vars;
138 }
139
140 /**
141 * Redirect the original category URL to the new one.
142 *
143 * @param array $query_vars Query vars to check for redirect var.
144 * @return array
145 */
146 public function request( $query_vars ) {
147 if ( isset( $query_vars['rank_math_category_redirect'] ) ) {
148 $catlink = trailingslashit( get_option( 'home' ) ) . user_trailingslashit( $query_vars['rank_math_category_redirect'], 'category' );
149 Helper::redirect( $catlink, 301 );
150 exit;
151 }
152
153 return $query_vars;
154 }
155
156 /**
157 * This function was taken and slightly adapted from WP No Category Base plugin by Saurabh Gupta.
158 *
159 * @return array
160 */
161 public function category_rewrite_rules() {
162 global $wp_rewrite;
163
164 $category_rewrite = $this->get_category_rules();
165
166 $old_base = str_replace( '%category%', '(.+)', $wp_rewrite->get_category_permastruct() );
167 $old_base = trim( $old_base, '/' );
168 $category_rewrite[ $old_base . '$' ] = 'index.php?rank_math_category_redirect=$matches[1]';
169
170 return $category_rewrite;
171 }
172
173 /**
174 * Remove the category base from the category link.
175 *
176 * @param string $link Term link.
177 * @param object $term Current Term Object.
178 * @param string $taxonomy Current Taxonomy.
179 * @return string
180 */
181 public function no_category_base( $link, $term, $taxonomy ) {
182 if ( 'category' !== $taxonomy ) {
183 return $link;
184 }
185
186 $category_base = get_option( 'category_base' );
187 if ( empty( $category_base ) ) {
188 global $wp_rewrite;
189 $category_base = trim( str_replace( '%category%', '', $wp_rewrite->get_category_permastruct() ), '/' );
190 }
191
192 // Remove initial slash, if there is one (we remove the trailing slash in the regex replacement and don't want to end up short a slash).
193 if ( '/' === substr( $category_base, 0, 1 ) ) {
194 $category_base = substr( $category_base, 1 );
195 }
196
197 $category_base .= '/';
198
199 return preg_replace( '`' . preg_quote( $category_base, '`' ) . '`u', '', $link, 1 );
200 }
201 /**
202 * Get category re-write rules.
203 *
204 * @return array
205 */
206 private function get_category_rules() {
207 global $wp_rewrite;
208
209 $category_rewrite = [];
210 $categories = $this->get_categories();
211 $blog_prefix = $this->get_blog_prefix();
212
213 if ( empty( $categories ) ) {
214 return $category_rewrite;
215 }
216
217 foreach ( $categories as $category ) {
218 $category_nicename = $this->get_category_parents( $category ) . $category->slug;
219 $category_rewrite = $this->add_category_rewrites( $category_rewrite, $category_nicename, $blog_prefix, $wp_rewrite->pagination_base );
220
221 // Add rules for upper case encoded nicename.
222 $category_nicename_filtered = $this->convert_encoded_to_upper( $category_nicename );
223
224 if ( $category_nicename !== $category_nicename_filtered ) {
225 $category_rewrite = $this->add_category_rewrites( $category_rewrite, $category_nicename_filtered, $blog_prefix, $wp_rewrite->pagination_base );
226 }
227 }
228
229 return $category_rewrite;
230 }
231
232 /**
233 * Adds required category rewrites rules.
234 *
235 * @param array $category_rewrite The current set of rules.
236 * @param string $category_nicename Category nicename.
237 * @param string $blog_prefix Multisite blog prefix.
238 * @param string $pagination_base WP_Query pagination base.
239 *
240 * @return array The added set of rules.
241 */
242 private function add_category_rewrites( $category_rewrite, $category_nicename, $blog_prefix, $pagination_base ) {
243
244 $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$' ] = 'index.php?category_name=$matches[1]&feed=$matches[2]';
245 $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/' . $pagination_base . '/?([0-9]{1,})/?$' ] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
246 $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/?$' ] = 'index.php?category_name=$matches[1]';
247
248 return $category_rewrite;
249 }
250
251 /**
252 * Walks through category nicename and convert encoded parts
253 * into uppercase using $this->encode_to_upper().
254 *
255 * @param string $name The encoded category URI string.
256 *
257 * @return string The converted URI string.
258 */
259 private function convert_encoded_to_upper( $name ) {
260 // Checks if name has any encoding in it.
261 if ( strpos( $name, '%' ) === false ) {
262 return $name;
263 }
264
265 $names = explode( '/', $name );
266 $names = array_map( [ $this, 'encode_to_upper' ], $names );
267
268 return implode( '/', $names );
269 }
270
271 /**
272 * Converts the encoded URI string to uppercase.
273 *
274 * @param string $encoded The encoded string.
275 *
276 * @return string The uppercased string.
277 */
278 private function encode_to_upper( $encoded ) {
279 if ( strpos( $encoded, '%' ) === false ) {
280 return $encoded;
281 }
282
283 return strtoupper( $encoded );
284 }
285
286 /**
287 * Retrieve category parents with separator.
288 *
289 * @param WP_Term $category Category instance.
290 *
291 * @return string
292 */
293 private function get_category_parents( $category ) {
294 if ( $category->parent === $category->cat_ID || absint( $category->parent ) < 1 ) {
295 return '';
296 }
297
298 $parents = get_category_parents( $category->parent, false, '/', true );
299 return is_wp_error( $parents ) ? '' : $parents;
300 }
301
302 /**
303 * Get categories with WPML compatibility.
304 *
305 * @return array
306 */
307 private function get_categories() {
308 /**
309 * Remove WPML filters while getting terms, to get all languages
310 */
311 Sitepress::get()->remove_term_filters();
312
313 $categories = get_categories( [ 'hide_empty' => false ] );
314
315 /**
316 * Register WPML filters back
317 */
318 Sitepress::get()->restore_term_filters();
319
320 return $categories;
321 }
322
323 /**
324 * Get the blog prefix.
325 *
326 * @return string
327 */
328 private function get_blog_prefix() {
329 $permalink_structure = get_option( 'permalink_structure' );
330 if ( is_multisite() && ! is_subdomain_install() && is_main_site() && 0 === strpos( $permalink_structure, '/blog/' ) ) {
331 return 'blog/';
332 }
333
334 return '';
335 }
336 }
337