PluginProbe
Redirection / 5.5.2
Redirection v5.5.2
5.10.0 5.9.0 5.8.1 5.8.0 3.7.2 3.7.3 4.0 4.0.1 4.1 4.1.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.3.1 4.3.2 4.3.3 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6.2 4.7.1 All 130 releases
redirection / models / permalinks.php

permalinks.php in Redirection 5.5.2, at models/permalinks.php

179 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Provides permalink migration facilities
5 */
6 class Red_Permalinks {
7 /**
8 * List of migrated permalink structures
9 *
10 * @var string[]
11 */
12 private $permalinks = [];
13
14 /**
15 * Current permalink structure
16 *
17 * @var string|null
18 */
19 private $current_permalink = null;
20
21 /**
22 * Constructor
23 *
24 * @param string[] $permalinks List of migrated permalinks.
25 */
26 public function __construct( $permalinks ) {
27 $this->permalinks = $permalinks;
28 }
29
30 /**
31 * Match and migrate any permalinks
32 *
33 * @param WP_Query $query Query.
34 * @return void
35 */
36 public function migrate( WP_Query $query ) {
37 global $wp, $wp_query;
38
39 if ( count( $this->permalinks ) === 0 ) {
40 return;
41 }
42
43 if ( ! $this->needs_migrating() ) {
44 return;
45 }
46
47 $this->intercept_permalinks();
48
49 $query_copy = clone $query;
50
51 foreach ( $this->permalinks as $old ) {
52 // Set the current permalink
53 $this->current_permalink = $old;
54
55 // Run the WP query again
56 $wp->init();
57 $wp->parse_request();
58
59 // Anything matched?
60 if ( $wp->matched_rule ) {
61 // Perform the post query
62 $wp->query_posts();
63
64 // A single post?
65 if ( is_single() && count( $query->posts ) > 0 ) {
66 // Restore permalinks
67 $this->release_permalinks();
68
69 // Get real URL from the post ID
70 $url = get_permalink( $query->posts[0]->ID );
71 if ( $url ) {
72 wp_safe_redirect( $url, 301, 'redirection' );
73 die();
74 }
75 }
76
77 // Reset the query back to the original
78 // phpcs:ignore
79 $wp_query = $query_copy;
80 break;
81 }
82 }
83
84 $this->release_permalinks();
85 }
86
87 /**
88 * Determine if the current request needs migrating. This is based on `WP::handle_404` in class-wp.php
89 *
90 * @return boolean
91 */
92 private function needs_migrating() {
93 global $wp_query;
94
95 // It's a 404 - shortcut to yes
96 if ( is_404() ) {
97 return true;
98 }
99
100 // Not admin pages
101 if ( is_admin() || is_robots() || is_favicon() ) {
102 return false;
103 }
104
105 if ( $wp_query->posts && ! $wp_query->is_posts_page && empty( $this->query_vars['page'] ) ) {
106 return false;
107 }
108
109 if ( ! is_paged() ) {
110 $author = get_query_var( 'author' );
111
112 // Don't 404 for authors without posts as long as they matched an author on this site.
113 if ( is_author() && is_numeric( $author ) && $author > 0 && is_user_member_of_blog( $author )
114 // Don't 404 for these queries if they matched an object.
115 || ( is_tag() || is_category() || is_tax() || is_post_type_archive() ) && get_queried_object()
116 // Don't 404 for these queries either.
117 || is_home() || is_search() || is_feed()
118 ) {
119 return false;
120 }
121 }
122
123 // If we've got this far then it's a 404
124 return true;
125 }
126
127 /**
128 * Hook the permalink options and return the migrated one
129 *
130 * @return void
131 */
132 private function intercept_permalinks() {
133 add_filter( 'pre_option_rewrite_rules', [ $this, 'get_old_rewrite_rules' ] );
134 add_filter( 'pre_option_permalink_structure', [ $this, 'get_old_permalink' ] );
135 }
136
137 /**
138 * Restore the hooked option
139 *
140 * @return void
141 */
142 private function release_permalinks() {
143 remove_filter( 'pre_option_rewrite_rules', [ $this, 'get_old_rewrite_rules' ] );
144 remove_filter( 'pre_option_permalink_structure', [ $this, 'get_old_permalink' ] );
145 }
146
147 /**
148 * Returns rewrite rules for the current migrated permalink
149 *
150 * @param array $rules Current rules.
151 * @return array
152 */
153 public function get_old_rewrite_rules( $rules ) {
154 global $wp_rewrite;
155
156 if ( $this->current_permalink ) {
157 $wp_rewrite->init();
158 $wp_rewrite->matches = 'matches';
159 return $wp_rewrite->rewrite_rules();
160 }
161
162 return $rules;
163 }
164
165 /**
166 * Get the current migrated permalink structure
167 *
168 * @param string $result Current value.
169 * @return string
170 */
171 public function get_old_permalink( $result ) {
172 if ( $this->current_permalink ) {
173 return $this->current_permalink;
174 }
175
176 return $result;
177 }
178 }
179