PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.2.7.3
Permalink Manager Lite v2.2.7.3
2.6.0 2.5.5 2.5.4 2.5.3.4 2.2.18 2.2.19.2 2.2.19.3 2.2.19.3.1 2.2.2 2.2.20 2.2.20.1 2.2.20.3 2.2.4 2.2.5 2.2.6 2.2.7.2 2.2.7.3 2.2.7.5 2.2.7.6 2.2.8.4 2.2.8.5 2.2.8.6 2.2.8.7 2.2.8.9 2.2.9.1 2.2.9.2 2.2.9.2.1 2.2.9.3 2.2.9.4 2.2.9.6 2.2.9.7 2.2.9.9 2.3.0 2.3.1.1 2.4.0 2.4.1 2.4.1.2 2.4.1.3 2.4.1.4 2.4.1.5 2.4.1.6 2.4.2 2.4.2.1 2.4.3 2.4.3.1 2.4.3.2 2.4.3.3 2.4.3.4 2.4.4 2.4.4.1 2.4.4.2 2.4.4.3 2.5.0 2.5.1 2.5.1.1 2.5.1.2 2.5.1.3 2.5.1.4 2.5.2 2.5.2.1 2.5.2.2 2.5.2.3 2.5.2.4 2.5.3 2.5.3.1 2.5.3.2 2.5.3.3 trunk 0.2 0.3 0.3.1 0.3.2 0.3.3 0.3.4 0.4 0.4.1 0.4.2 0.4.3 0.4.4 0.4.6 0.4.7 0.4.8 0.4.9 0.5.3 0.5.4 1.0.0 1.0.1 1.0.4 1.1.0 1.1.1 1.1.2 1.11.6.3 2.0.0 2.0.3 2.0.4 2.0.4.3 2.0.5.1 2.0.5.2 2.0.5.3 2.0.5.3.1 2.0.5.4 2.0.5.4a 2.0.5.5 2.0.5.6 2.0.5.6.1 2.0.5.7 2.0.5.9a 2.0.6.2.1 2.0.6.2a 2.0.6.3 2.1.0 2.1.1 2.1.2.4 2.2.0 2.2.1.1 2.2.1.2 2.2.11 2.2.12 2.2.13.1 2.2.14 2.2.15.1 2.2.16 2.2.17
permalink-manager / includes / core / permalink-manager-core-functions.php
permalink-manager / includes / core Last commit date
permalink-manager-actions.php 6 years ago permalink-manager-admin-functions.php 6 years ago permalink-manager-core-functions.php 6 years ago permalink-manager-debug.php 6 years ago permalink-manager-gutenberg.php 6 years ago permalink-manager-helper-functions.php 6 years ago permalink-manager-third-parties.php 6 years ago permalink-manager-uri-functions-post.php 6 years ago
permalink-manager-core-functions.php
715 lines
1 <?php
2
3 /**
4 * Core functions
5 */
6 class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
7
8 public function __construct() {
9 add_action( 'init', array($this, 'init_hooks'), 99);
10 }
11
12 function init_hooks() {
13 global $permalink_manager_options;
14
15 // Trailing slashes
16 add_filter( 'permalink_manager_filter_final_term_permalink', array($this, 'control_trailing_slashes'), 9);
17 add_filter( 'permalink_manager_filter_final_post_permalink', array($this, 'control_trailing_slashes'), 9);
18 add_filter( 'permalink_manager_filter_post_sample_uri', array($this, 'control_trailing_slashes'), 9);
19
20 /**
21 * Detect & canonical URL/redirect functions
22 */
23 // Do not trigger in back-end
24 if(is_admin()) { return false; }
25
26 // Do not trigger if Customizer is loaded
27 if(function_exists('is_customize_preview') && is_customize_preview()) { return false; }
28
29 // Do not trigger if Elementor is loaded
30 if((!empty($_REQUEST['action']) && $_REQUEST['action'] == 'elementor') || isset($_REQUEST['elementor-preview'])) { return false; }
31
32 // Use the URIs set in this plugin
33 add_filter( 'request', array($this, 'detect_post'), 0, 1 );
34
35 // Redirect from old URIs to new URIs + adjust canonical redirect settings
36 add_action( 'template_redirect', array($this, 'new_uri_redirect_and_404'), 1);
37 add_action( 'wp', array($this, 'adjust_canonical_redirect'), 0, 1);
38
39 // Case insensitive permalinks
40 if(!empty($permalink_manager_options['general']['case_insensitive_permalinks'])) {
41 add_action( 'parse_request', array($this, 'case_insensitive_permalinks'), 0);
42 }
43 // Force 404 on non-existing pagination pages
44 if(!empty($permalink_manager_options['general']['pagination_redirect'])) {
45 add_action( 'wp', array($this, 'fix_pagination_pages'), 0);
46 }
47 }
48
49 /**
50 * The most important Permalink Manager function
51 */
52 public static function detect_post($query, $request_url = false, $return_object = false) {
53 global $wpdb, $wp, $wp_rewrite, $permalink_manager, $permalink_manager_uris, $wp_filter, $permalink_manager_options, $pm_query;
54
55 // Check if the array with custom URIs is set
56 //if(!(is_array($permalink_manager_uris)) || (empty($query) && empty($request_url))) return $query;
57 if(!(is_array($permalink_manager_uris))) return $query;
58
59 // Used in debug mode & endpoints
60 $old_query = $query;
61
62 /**
63 * 1. Prepare URL and check if it is correct (make sure that both requested URL & home_url share the same protoocl and get rid of www prefix)
64 */
65 $request_url = (!empty($request_url)) ? parse_url($request_url, PHP_URL_PATH) : $_SERVER['REQUEST_URI'];
66 $request_url = strtok($request_url, "?");
67
68 $request_url = sprintf("http://%s%s", str_replace("www.", "", $_SERVER['HTTP_HOST']), $request_url);
69 $raw_home_url = trim(get_option('home'));
70 $home_url = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $raw_home_url);
71
72 if(filter_var($request_url, FILTER_VALIDATE_URL)) {
73 // Check if "Deep Detect" is enabled
74 $deep_detect_enabled = apply_filters('permalink_manager_deep_uri_detect', $permalink_manager_options['general']['deep_detect']);
75
76 // Keep only the URI
77 $request_url = str_replace($home_url, "", $request_url);
78
79 // Hotfix for language plugins
80 if(filter_var($request_url, FILTER_VALIDATE_URL)) {
81 $request_url = parse_url($request_url, PHP_URL_PATH);
82 }
83
84 $request_url = trim($request_url, "/");
85
86 // Get all the endpoints & pattern
87 $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
88 $pattern = "/^(.+?)(?|\/({$endpoints})(?|\/(.*)|$)|\/()([\d]+)\/?)?$/i";
89
90 // Use default REGEX to detect post
91 preg_match($pattern, $request_url, $regex_parts);
92 $uri_parts['lang'] = false;
93 $uri_parts['uri'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
94 $uri_parts['endpoint'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
95 $uri_parts['endpoint_value'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
96
97 // Allow to filter the results by third-parties + store the URI parts with $pm_query global
98 $uri_parts = $pm_query = apply_filters('permalink_manager_detect_uri', $uri_parts, $request_url, $endpoints);
99
100 // Support comment pages
101 preg_match("/(.*)\/{$wp_rewrite->comments_pagination_base}-([\d]+)/", $request_url, $regex_parts);
102 if(!empty($regex_parts[2])) {
103 $uri_parts['uri'] = $regex_parts[1];
104 $uri_parts['endpoint'] = 'cpage';
105 $uri_parts['endpoint_value'] = $regex_parts[2];
106 }
107
108 // Support pagination endpoint
109 if($uri_parts['endpoint'] == $wp_rewrite->pagination_base) {
110 $uri_parts['endpoint'] = 'page';
111 }
112
113 // Stop the function if $uri_parts is empty
114 if(empty($uri_parts)) return $query;
115
116 // Get the URI parts from REGEX parts
117 $lang = $uri_parts['lang'];
118 $uri = $uri_parts['uri'];
119 $endpoint = $uri_parts['endpoint'];
120 $endpoint_value = $uri_parts['endpoint_value'];
121
122 // Trim slashes
123 $uri = trim($uri, "/");
124
125 // Ignore URLs with no URI grabbed
126 if(empty($uri)) return $query;
127
128 // Flip array for better performance
129 $all_uris = array_flip($permalink_manager_uris);
130
131 // Attempt 1.
132 // Find the element ID
133 $element_id = isset($all_uris[$uri]) ? $all_uris[$uri] : false;
134
135 // Atempt 2.
136 // Decode both request URI & URIs array & make them lowercase (and save in a separate variable)
137 if(empty($element_id)) {
138 $uri = strtolower(urldecode($uri));
139
140 foreach($all_uris as $raw_uri => $uri_id) {
141 $raw_uri = urldecode($raw_uri);
142 $all_uris[$raw_uri] = $uri_id;
143 }
144
145 // Convert array keys lowercase
146 $all_uris = array_change_key_case($all_uris, CASE_LOWER);
147
148 $element_id = isset($all_uris[$uri]) ? $all_uris[$uri] : $element_id;
149 }
150
151 // Atempt 3.
152 // Check again in case someone used post/tax IDs instead of slugs
153 //if(empty($element_id) && $deep_detect_enabled && (isset($old_query['page']))) {
154 if($deep_detect_enabled && is_numeric($endpoint_value) && isset($all_uris["{$uri}/{$endpoint_value}"])) {
155 $element_id = $all_uris["{$uri}/{$endpoint_value}"];
156 $endpoint_value = $endpoint = "";
157 }
158
159 // Atempt 4.
160 // Check again for attachment custom URIs
161 if(empty($element_id) && isset($old_query['attachment'])) {
162 $element_id = isset($all_uris["{$uri}/{$endpoint}/{$endpoint_value}"]) ? $all_uris["{$uri}/{$endpoint}/{$endpoint_value}"] : $element_id;
163
164 if($element_id) {
165 $endpoint_value = $endpoint = "";
166 }
167 }
168
169 // Allow to filter the item_id by third-parties after initial detection
170 $element_id = apply_filters('permalink_manager_detected_element_id', $element_id, $uri_parts, $request_url);
171
172 // Clear the original query before it is filtered
173 $query = ($element_id) ? array() : $query;
174
175 /**
176 * 3A. Custom URI assigned to taxonomy
177 */
178 if(strpos($element_id, 'tax-') !== false) {
179 // Remove the "tax-" prefix
180 $term_id = intval(preg_replace("/[^0-9]/", "", $element_id));
181
182 // Filter detected post ID
183 $term_id = apply_filters('permalink_manager_detected_term_id', intval($term_id), $uri_parts, true);
184
185 // Get the variables to filter wp_query and double-check if taxonomy exists
186 $term = get_term($term_id);
187 $term_taxonomy = (!empty($term->taxonomy)) ? $term->taxonomy : false;
188
189 // Check if taxonomy is allowed
190 $disabled = (Permalink_Manager_Helper_Functions::is_disabled($term_taxonomy, 'taxonomy')) ? true : false;
191
192 // Proceed only if the term is not removed and its taxonomy is not disabled
193 if(!$disabled && $term_taxonomy) {
194 // Get some term data
195 if($term_taxonomy == 'category') {
196 $query_parameter = 'category_name';
197 } else if($term_taxonomy == 'post_tag') {
198 $query_parameter = 'tag';
199 } else {
200 $query["taxonomy"] = $term_taxonomy;
201 $query_parameter = $term_taxonomy;
202 }
203 $term_ancestors = get_ancestors($term_id, $term_taxonomy);
204 $final_uri = $term->slug;
205
206 // Fix for hierarchical terms
207 if(!empty($term_ancestors)) {
208 foreach ($term_ancestors as $parent_id) {
209 $parent = get_term((int) $parent_id, $term_taxonomy);
210 if(!empty($parent->slug)) {
211 $final_uri = $parent->slug . '/' . $final_uri;
212 }
213 }
214 }
215
216 //$query["term"] = $final_uri;
217 $query["term"] = $term->slug;
218 //$query[$query_parameter] = $final_uri;
219 $query[$query_parameter] = $term->slug;
220 } else {
221 $broken_uri = true;
222 }
223 }
224 /**
225 * 3B. Custom URI assigned to post/page/cpt item
226 */
227 else if(isset($element_id) && is_numeric($element_id)) {
228 // Fix for revisions
229 $is_revision = wp_is_post_revision($element_id);
230 $element_id = ($is_revision) ? $is_revision : $element_id;
231
232 // Filter detected post ID
233 $element_id = apply_filters('permalink_manager_detected_post_id', $element_id, $uri_parts);
234
235 $post_to_load = get_post($element_id);
236 $final_uri = (!empty($post_to_load->post_name)) ? $post_to_load->post_name : false;
237 $post_type = (!empty($post_to_load->post_type)) ? $post_to_load->post_type : false;
238
239 // Check if post type is allowed
240 $disabled = (Permalink_Manager_Helper_Functions::is_disabled($post_type, 'post_type')) ? true : false;
241
242 // Proceed only if the term is not removed and its taxonomy is not disabled
243 if(!$disabled && $post_type) {
244 $post_type_object = get_post_type_object($post_type);
245
246 // Fix for hierarchical CPT & pages
247 if(!(empty($post_to_load->ancestors)) && !empty($post_type_object->hierarchical)) {
248 foreach ($post_to_load->ancestors as $parent) {
249 $parent = get_post( $parent );
250 if($parent && $parent->post_name) {
251 $final_uri = $parent->post_name . '/' . $final_uri;
252 }
253 }
254 }
255
256 // Alter query parameters + support drafts URLs
257 if($post_to_load->post_status == 'draft' || empty($final_uri)) {
258 if(is_user_logged_in()) {
259 $query['p'] = $element_id;
260 $query['preview'] = true;
261 $query['post_type'] = $post_type;
262 } else if($post_to_load->post_status == 'draft') {
263 $query['pagename'] = '-';
264 $query['error'] = '404';
265
266 $element_id = 0;
267 } else {
268 $query = $old_query;
269 }
270 } else if($post_type == 'page') {
271 $query['pagename'] = $final_uri;
272 // $query['post_type'] = $post_type;
273 } else if($post_type == 'post') {
274 $query['name'] = $final_uri;
275 } else if($post_type == 'attachment') {
276 $query['attachment'] = $final_uri;
277 } else {
278 // Get the query var
279 $query_var = (!empty($post_type_object->query_var)) ? $post_type_object->query_var : $post_type;
280
281 $query['name'] = $final_uri;
282 $query['post_type'] = $post_type;
283 $query[$query_var] = $final_uri;
284 }
285 } else {
286 $broken_uri = true;
287 }
288 }
289
290 /**
291 * 4. Auto-remove removed term custom URI & redirects (works if enabled in plugin settings)
292 */
293 if(!empty($broken_uri) && !empty($permalink_manager_options['general']['auto_remove_duplicates'])) {
294 $remove_broken_uri = Permalink_Manager_Actions::clear_single_element_uris_and_redirects($element_id);
295
296 // Reload page if success
297 if($remove_broken_uri) {
298 header("Refresh:0");
299 exit();
300 }
301 }
302
303 /**
304 * 5A. Endpoints
305 */
306 if(!empty($element_id) && (!empty($endpoint) || !empty($endpoint_value))) {
307 if(is_array($endpoint)) {
308 foreach($endpoint as $endpoint_name => $endpoint_value) {
309 $query[$endpoint_name] = $endpoint_value;
310 }
311 } else if($endpoint == 'feed') {
312 $query[$endpoint] = 'feed';
313 } else if($endpoint == 'page') {
314 $endpoint = 'paged';
315 $query[$endpoint] = $endpoint_value;
316 } else if($endpoint == 'trackback') {
317 $endpoint = 'tb';
318 $query[$endpoint] = 1;
319 } else if(!$endpoint && is_numeric($endpoint_value)) {
320 $query['page'] = $endpoint_value;
321 } else {
322 $query[$endpoint] = $endpoint_value;
323 }
324
325 // Fix for attachments
326 if(!empty($query['attachment'])) {
327 $query = array('attachment' => $query['attachment'], 'do_not_redirect' => 1);
328 }
329 }
330
331 /**
332 * 5B. Endpoints - check if any endpoint is set with $_GET parameter
333 */
334 if(!empty($element_id) && $deep_detect_enabled && !empty($_GET)) {
335 $get_endpoints = array_intersect($wp->public_query_vars, array_keys($_GET));
336
337 if(!empty($get_endpoints)) {
338 // Append query vars from $_GET parameters
339 foreach($get_endpoints as $endpoint) {
340 // Numeric endpoints
341 $endpoint_value = (in_array($endpoint, array('page', 'paged', 'attachment_id'))) ? filter_var($_GET[$endpoint], FILTER_SANITIZE_NUMBER_INT) : $_GET[$endpoint];
342 $query[$endpoint] = sanitize_text_field($endpoint_value);
343 }
344 }
345 }
346
347 /**
348 * 6. Set global with detected item id
349 */
350 if(!empty($element_id)) {
351 $pm_query['id'] = $element_id;
352
353 // Make the redirects more clever - see new_uri_redirect_and_404() method
354 $query['do_not_redirect'] = 1;
355 }
356 }
357
358 /**
359 * 7. Debug data
360 */
361 if(!empty($taxonomy)) {
362 $content_type = "Taxonomy: {$term_taxonomy}";
363 } else if(!empty($post_type)) {
364 $content_type = "Post type: {$post_type}";
365 } else {
366 $content_type = '';
367 }
368 $query = apply_filters('permalink_manager_filter_query', $query, $old_query, $uri_parts, $pm_query, $content_type);
369
370 if($return_object && !empty($term)) {
371 return $term;
372 } else if($return_object && !empty($post_to_load)) {
373 return $post_to_load;
374 } else {
375 return $query;
376 }
377 }
378
379 /**
380 * Trailing slash & remove BOM and double slashes
381 */
382 static function control_trailing_slashes($permalink) {
383 global $permalink_manager_options;
384
385 // Ignore empty permalinks
386 if(empty($permalink)) { return $permalink; }
387
388 $trailing_slash_setting = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : "";
389
390 // Do not append the trailing slash if permalink contains hashtag or get parameters
391 $url_parsed = parse_url($permalink);
392
393 if(!empty($url_parsed['query']) || !empty($url_parsed['fragment']) || preg_match("/.*\.([a-zA-Z]{3,4})\/?$/", $permalink)) {
394 $permalink = untrailingslashit($permalink);
395 } else if(in_array($trailing_slash_setting, array(1, 10))) {
396 $permalink = trailingslashit($permalink);
397 } else if(in_array($trailing_slash_setting, array(2, 20))) {
398 $permalink = untrailingslashit($permalink);
399 }
400
401 // Remove double slashes
402 $permalink = preg_replace('/([^:])(\/{2,})/', '$1/', $permalink);
403
404 // Remove trailing slashes from URLs with extensions
405 $permalink = preg_replace("/(\.[a-z]{3,4})\/$/i", "$1", $permalink);
406
407 return $permalink;
408 }
409
410 /**
411 * Display 404 if requested page does not exist in pagination
412 */
413 function fix_pagination_pages() {
414 global $wp_query;
415
416 // 1. Get the queried object
417 $post = get_queried_object();
418
419 // 2. Check if post object is defined
420 if(!empty($post->post_type)) {
421 // 2A. Check if pagination is detected
422 $current_page = (!empty($wp_query->query_vars['page'])) ? $wp_query->query_vars['page'] : 1;
423 $current_page = (empty($wp_query->query_vars['page']) && !empty($wp_query->query_vars['paged'])) ? $wp_query->query_vars['paged'] : $current_page;
424
425 // 2B. Count post pages
426 $num_pages = substr_count(strtolower($post->post_content), '<!--nextpage-->') + 1;
427
428 $is_404 = ($current_page > 1 && ($current_page > $num_pages)) ? true : false;
429 }
430 // 3. Force 404 if no posts are loaded
431 else if(!empty($wp_query->query['paged']) && $wp_query->post_count == 0) {
432 $is_404 = true;
433 }
434
435 // 5. Block non-existent pages (Force 404 error)
436 if(!empty($is_404)) {
437 $wp_query->is_404 = true;
438 $wp_query->query = $wp_query->queried_object = $wp_query->queried_object_id = null;
439 $wp_query->set_404();
440
441 status_header(404);
442 nocache_headers();
443 include(get_query_template('404'));
444
445 die();
446 }
447 }
448
449 /**
450 * Redirects
451 */
452 function new_uri_redirect_and_404() {
453 global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_external_redirects, $permalink_manager_options, $wp, $pm_query;
454
455 // Get the redirection mode & trailing slashes settings
456 $redirect_mode = (!empty($permalink_manager_options['general']['redirect'])) ? $permalink_manager_options['general']['redirect'] : false;
457 $trailing_slashes_mode = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : false;
458 $trailing_slashes_redirect_mode = (!empty($permalink_manager_options['general']['trailing_slashes_redirect'])) ? $permalink_manager_options['general']['trailing_slashes_redirect'] : 301;
459 $redirect_type = '-';
460
461 // Get home URL
462 $home_url = rtrim(get_option('home'), "/");
463 $home_dir = parse_url($home_url, PHP_URL_PATH);
464
465 // Set up $correct_permalink variable
466 $correct_permalink = '';
467
468 // Get query string & URI
469 $query_string = $_SERVER['QUERY_STRING'];
470 $old_uri = $_SERVER['REQUEST_URI'];
471
472 // Fix for WP installed in directories (remove the directory name from the URI)
473 if(!empty($home_dir)) {
474 $home_dir_regex = preg_quote(trim($home_dir), "/");
475 $old_uri = preg_replace("/{$home_dir_regex}/", "", $old_uri, 1);
476 }
477
478 // Do not use custom redirects on author pages, search & front page
479 if(!is_author() && !is_front_page() && !is_home() && !is_feed() && !is_search() && empty($_GET['s'])) {
480
481 // Unset 404 if custom URI is detected
482 if(isset($pm_query['id'])) {
483 $wp_query->is_404 = false;
484 }
485
486 // Sometimes $wp_query indicates the wrong object if requested directly
487 $queried_object = get_queried_object();
488
489 /**
490 * 1A. External redirect
491 */
492 if(!empty($pm_query['id']) && !empty($permalink_manager_external_redirects[$pm_query['id']])) {
493 $external_url = $permalink_manager_external_redirects[$pm_query['id']];
494
495 if(filter_var($external_url, FILTER_VALIDATE_URL)) {
496 // Allow redirect
497 $wp_query->query_vars['do_not_redirect'] = 0;
498
499 wp_redirect($external_url, 301, PERMALINK_MANAGER_PLUGIN_NAME);
500 exit();
501 }
502 }
503
504 /**
505 * 1B. Custom redirects
506 */
507 if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request) && !empty($pm_query['uri'])) {
508 $uri = $pm_query['uri'];
509 $endpoint_value = $pm_query['endpoint_value'];
510
511 // Make sure that URIs with non-ASCII characters are also detected + Check the URLs that end with number
512 $decoded_url = urldecode($uri);
513 $endpoint_url = "{$uri}/{$endpoint_value}";
514
515 // Check if the URI is not assigned to any post/term's redirects
516 foreach($permalink_manager_redirects as $element => $redirects) {
517 if(!is_array($redirects)) { continue; }
518
519 if(in_array($uri, $redirects) || in_array($decoded_url, $redirects) || (is_numeric($endpoint_value) && in_array($endpoint_url, $redirects))) {
520
521 // Post is detected
522 if(is_numeric($element)) {
523 $correct_permalink = get_permalink($element);
524 }
525 // Term is detected
526 else {
527 $term_id = intval(preg_replace("/[^0-9]/", "", $element));
528 $correct_permalink = get_term_link($term_id);
529 }
530 }
531 }
532
533 $redirect_type = (!empty($correct_permalink)) ? 'custom_redirect' : $redirect_type;
534 }
535
536 // Ignore WP-Content links
537 if(!empty($_SERVER['REQUEST_URI']) && (strpos($_SERVER['REQUEST_URI'], '/wp-content') !== false)) { return false; }
538
539 /**
540 * 1C. Enhance native redirect
541 */
542 if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) {
543
544 // Affect only posts with custom URI and old URIs
545 if(!empty($queried_object->ID) && isset($permalink_manager_uris[$queried_object->ID]) && empty($wp_query->query['preview'])) {
546 // Ignore posts with specific statuses
547 if(!(empty($queried_object->post_status)) && in_array($queried_object->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
548 return '';
549 }
550
551 // Check if post type is allowed
552 if(Permalink_Manager_Helper_Functions::is_disabled($queried_object->post_type, 'post_type')) { return ''; }
553
554 // Get the real URL
555 $correct_permalink = get_permalink($queried_object->ID);
556 }
557 // Affect only terms with custom URI and old URIs
558 else if(!empty($queried_object->term_id) && isset($permalink_manager_uris["tax-{$queried_object->term_id}"]) && defined('PERMALINK_MANAGER_PRO')) {
559 // Check if taxonomy is allowed
560 if(Permalink_Manager_Helper_Functions::is_disabled($queried_object->taxonomy, "taxonomy")) { return ''; }
561
562 // Get the real URL
563 $correct_permalink = get_term_link($queried_object->term_id, $queried_object->taxonomy);
564 }
565
566 $redirect_type = (!empty($correct_permalink)) ? 'native_redirect' : $redirect_type;
567 }
568
569 /**
570 * 2. Check trailing slashes (ignore links with query parameters)
571 */
572 if($trailing_slashes_mode && empty($_SERVER['QUERY_STRING']) && !empty($_SERVER['REQUEST_URI'])) {
573 // Check if $old_uri ends with slash or not
574 $ends_with_slash = (substr($old_uri, -1) == "/") ? true : false;
575 $trailing_slashes_mode = (preg_match("/.*\.([a-zA-Z]{3,4})\/?$/", $old_uri) && $trailing_slashes_mode == 10) ? 20 : $trailing_slashes_mode;
576
577 // Ignore empty URIs
578 if($old_uri != "/") {
579 // Remove the trailing slashes (and add them again if needed below)
580 $old_uri = trim($old_uri, "/");
581 $correct_permalink = (!empty($correct_permalink)) ? trim($correct_permalink, "/") : "";
582
583 // 2A. Force trailing slashes
584 if($trailing_slashes_mode == 10 && $ends_with_slash == false) {
585 $correct_permalink = (!empty($correct_permalink)) ? "{$correct_permalink}/" : "{$home_url}/{$old_uri}/";
586 }
587 // 2B. Remove trailing slashes
588 else if($trailing_slashes_mode == 20 && $ends_with_slash == true) {
589 $correct_permalink = (!empty($correct_permalink)) ? $correct_permalink : "{$home_url}/{$old_uri}";
590 $correct_permalink = trim($correct_permalink, "/");
591 }
592
593 // Use redirect mode set for trailing slash redirect
594 if(($trailing_slashes_mode == 20 && $ends_with_slash == true) || ($trailing_slashes_mode == 10 && $ends_with_slash == false)) {
595 $redirect_mode = $trailing_slashes_redirect_mode;
596 }
597 }
598
599 $redirect_type = (!empty($correct_permalink)) ? 'slash_redirect' : '-';
600 }
601
602 /**
603 * 3. Check if URL contains duplicated slashes
604 */
605 if(!empty($old_uri) && ($old_uri != '/') && preg_match('/\/{2,}/', $old_uri)) {
606 $new_uri = ltrim(preg_replace('/([^:])([\/]+)/', '$1/', $old_uri), "/");
607 $correct_permalink = "{$home_url}/{$new_uri}";
608 }
609
610 /**
611 * 4. Prevent redirect loop
612 */
613 if(!empty($correct_permalink) && is_string($correct_permalink) && !empty($wp->request) && !empty($redirect_type) && $redirect_type !== 'slash_redirect') {
614 $current_uri = trim($wp->request, "/");
615 $redirect_uri = trim(parse_url($correct_permalink, PHP_URL_PATH), "/");
616
617 $correct_permalink = ($redirect_uri == $current_uri) ? null : $correct_permalink;
618 }
619 } else {
620 $queried_object = '-';
621 }
622
623 /**
624 * 5. WWW prefix | SSL mismatch redirect
625 */
626 if(!empty($permalink_manager_options['general']['sslwww_redirect'])) {
627 $home_url_has_www = (strpos($home_url, 'www.') !== false) ? true : false;
628 $requested_url_has_www = (strpos($_SERVER['HTTP_HOST'], 'www.') !== false) ? true : false;
629 $home_url_has_ssl = (strpos($home_url, 'https') !== false) ? true : false;
630 $requested_url_has_ssl = is_ssl();
631
632 if(($home_url_has_www !== $requested_url_has_www) || ($home_url_has_ssl !== $requested_url_has_ssl)) {
633 $correct_permalink = "{$home_url}/{$old_uri}";
634 $redirect_type = 'www_redirect';
635 }
636 }
637
638 /**
639 * 6. Debug redirect
640 */
641 $correct_permalink = apply_filters('permalink_manager_filter_redirect', $correct_permalink, $redirect_type, $queried_object);
642
643 /**
644 * 7. Ignore default URIs (or do nothing if redirects are disabled)
645 */
646 if(!empty($correct_permalink) && is_string($correct_permalink) && !empty($redirect_mode)) {
647 // Allow redirect
648 $wp_query->query_vars['do_not_redirect'] = 0;
649
650 // Append query string
651 $correct_permalink = (!empty($query_string)) ? sprintf("%s?%s", strtok($correct_permalink, "?"), $query_string) : $correct_permalink;
652
653 // Adjust trailing slashes
654 $correct_permalink = self::control_trailing_slashes($correct_permalink);
655
656 wp_safe_redirect($correct_permalink, $redirect_mode, PERMALINK_MANAGER_PLUGIN_NAME);
657 exit();
658 }
659 }
660
661 function adjust_canonical_redirect() {
662 global $permalink_manager_options, $permalink_manager_uris, $wp, $wp_rewrite;
663
664 // Adjust rewrite settings for trailing slashes
665 $trailing_slash_setting = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : "";
666 if(in_array($trailing_slash_setting, array(1, 10))) {
667 $wp_rewrite->use_trailing_slashes = true;
668 } else if(in_array($trailing_slash_setting, array(2, 20))) {
669 $wp_rewrite->use_trailing_slashes = false;
670 }
671
672 // Get endpoints
673 $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
674 $endpoints_array = ($endpoints) ? explode("|", $endpoints) : array();
675
676 // Check if any endpoint is called (fix for feed and similar endpoints)
677 foreach($endpoints_array as $endpoint) {
678 if(!empty($wp->query_vars[$endpoint])) {
679 $wp->query_vars['do_not_redirect'] = 1;
680 break;
681 }
682 }
683
684 // Do nothing for posts and terms without custom URIs (when canonical redirect is enabled)
685 if(is_singular() || is_tax() || is_category() || is_tag()) {
686 $element = get_queried_object();
687 if(!empty($element->ID)) {
688 $custom_uri = (!empty($permalink_manager_uris[$element->ID])) ? $permalink_manager_uris[$element->ID] : "";
689 } else if(!empty($element->term_id)) {
690 $custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : "";
691 }
692 }
693
694 if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) {
695 remove_action('template_redirect', 'wp_old_slug_redirect');
696 remove_action('template_redirect', 'redirect_canonical');
697 add_filter('wpml_is_redirected', '__return_false', 99, 2);
698 add_filter('pll_check_canonical_url', '__return_false', 99, 2);
699 }
700 }
701
702 /**
703 * Case insensitive permalinks
704 */
705 function case_insensitive_permalinks() {
706 global $permalink_manager_options, $permalink_manager_uris;
707
708 if(!empty($_SERVER['REQUEST_URI'])) {
709 $_SERVER['REQUEST_URI'] = strtolower($_SERVER['REQUEST_URI']);
710 $permalink_manager_uris = array_map('strtolower', $permalink_manager_uris);
711 }
712 }
713
714 }
715