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 |