PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.0.5.3
Permalink Manager Lite v2.0.5.3
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 8 years ago permalink-manager-admin-functions.php 8 years ago permalink-manager-core-functions.php 8 years ago permalink-manager-helper-functions.php 8 years ago permalink-manager-third-parties.php 8 years ago permalink-manager-uri-functions-post.php 8 years ago
permalink-manager-core-functions.php
513 lines
1 <?php
2
3 /**
4 * Core function
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 // Trigger only in front-end
14 if(!is_admin()) {
15 // Use the URIs set in this plugin
16 add_filter( 'request', array($this, 'detect_post'), 0, 1 );
17
18 // Trailing slashes
19 add_filter( 'permalink_manager_filter_final_term_permalink', array($this, 'control_trailing_slashes'), 9);
20 add_filter( 'permalink_manager_filter_final_post_permalink', array($this, 'control_trailing_slashes'), 9);
21 add_filter( 'permalink_manager_filter_post_sample_permalink', array($this, 'control_trailing_slashes'), 9);
22
23 // Redirect from old URIs to new URIs + adjust canonical redirect settings
24 add_action( 'template_redirect', array($this, 'new_uri_redirect_and_404'), 1);
25 add_action( 'wp', array($this, 'adjust_canonical_redirect'), 0, 1);
26
27 // Case insensitive permalinks
28 add_action( 'parse_request', array($this, 'case_insensitive_permalinks'), 0);
29 add_action( 'parse_request', array($this, 'fix_pagination_pages'), 0);
30 }
31 }
32
33 /**
34 * The most important Permalink Manager function
35 */
36 function detect_post($query) {
37 global $wpdb, $wp, $wp_rewrite, $permalink_manager_uris, $wp_filter, $permalink_manager_options, $pm_item_id;
38
39 // Check if any custom URI is used and we are not in WP-Admin dashboard
40 if(!(is_array($permalink_manager_uris)) || empty($query)) return $query;
41
42 // Used in debug mode & endpoints
43 $old_query = $query;
44
45 /**
46 * 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)
47 */
48 $request_url = sprintf("http://%s%s", str_replace("www.", "", $_SERVER['HTTP_HOST']), strtok($_SERVER['REQUEST_URI'], "?"));
49 $raw_home_url = trim(get_option('home'));
50 $home_url = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $raw_home_url);
51
52 if(filter_var($request_url, FILTER_VALIDATE_URL)) {
53 // Check if "Deep Detect" is enabled
54 $deep_detect_enabled = apply_filters('permalink-manager-deep-uri-detect', $permalink_manager_options['general']['deep_detect']);
55
56 // Keep only the URI
57 $request_url = trim(str_replace($home_url, "", $request_url), "/");
58
59 // Get all the endpoints & pattern
60 $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
61 $pattern = "/^(.+?)(?|\/({$endpoints})\/?([^\/]*)|()\/([\d+]))?\/?$/i";
62
63 // Use default REGEX to detect post
64 preg_match($pattern, $request_url, $regex_parts);
65 $uri_parts['lang'] = false;
66 $uri_parts['uri'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
67 $uri_parts['endpoint'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
68 $uri_parts['endpoint_value'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
69
70 // Allow to filter the results by third-parties
71 $uri_parts = apply_filters('permalink-manager-detect-uri', $uri_parts, $request_url, $endpoints);
72
73 // Stop the function if $uri_parts is empty
74 if(empty($uri_parts)) return $query;
75
76 // Get the URI parts from REGEX parts
77 $lang = $uri_parts['lang'];
78 $uri = $uri_parts['uri'];
79 $endpoint = $uri_parts['endpoint'];
80 $endpoint_value = $uri_parts['endpoint_value'];
81
82 // Trim slashes
83 $uri = trim($uri, "/");
84
85 // Decode both Request URI & URIs array
86 $uri = urldecode($uri);
87 foreach ($permalink_manager_uris as $key => $value) {
88 $permalink_manager_uris[$key] = urldecode($value);
89 }
90
91 // Ignore URLs with no URI grabbed
92 if(empty($uri)) return $query;
93
94 /**
95 * 2. Check if found URI matches any element from custom uris array
96 */
97 $element_id = array_search($uri, $permalink_manager_uris);
98
99 // Check again in case someone added .html suffix to particular post (with .html suffix)
100 $element_id = (empty($element_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $element_id;
101
102 // Check again in case someone used post/tax IDs instead of slugs
103 if($deep_detect_enabled && isset($old_query['page'])) {
104
105 $new_item_id = array_search("{$uri}/{$endpoint_value}", $permalink_manager_uris);
106 if($new_item_id) {
107 $element_id = $new_item_id;
108 $endpoint_value = $endpoint = "";
109 }
110 }
111
112 // Allow to filter the item_id by third-parties after initial detection
113 $element_id = apply_filters('permalink-manager-detected-initial-id', $element_id, $uri_parts, $request_url);
114
115 // Clear the original query before it is filtered
116 $query = ($element_id) ? array() : $query;
117
118 /**
119 * 3A. Custom URI assigned to taxonomy
120 */
121 if(strpos($element_id, 'tax-') !== false) {
122 // Remove the "tax-" prefix
123 $term_id = intval(preg_replace("/[^0-9]/", "", $element_id));
124
125 // Filter detected post ID
126 $term_id = apply_filters('permalink-manager-detected-term-id', intval($term_id), $uri_parts, true);
127
128 // Get the variables to filter wp_query and double-check if taxonomy exists
129 $term = get_term($term_id);
130 $term_taxonomy = (!empty($term->taxonomy)) ? $term->taxonomy : false;
131
132 // Check if taxonomy is allowed
133 $disabled = (Permalink_Manager_Helper_Functions::is_disabled($term_taxonomy, 'taxonomy')) ? true : false;
134
135 // Proceed only if the term is not removed and its taxonomy is not disabled
136 if(!$disabled && $term_taxonomy) {
137 // Get some term data
138 if($term_taxonomy == 'category') {
139 $query_parameter = 'category_name';
140 } else if($term_taxonomy == 'post_tag') {
141 $query_parameter = 'tag';
142 } else {
143 $query_parameter = $term_taxonomy;
144 }
145 $term_ancestors = get_ancestors($term_id, $term_taxonomy);
146 $final_uri = $term->slug;
147
148 // Fix for hierarchical terms
149 if(empty($term_ancestors)) {
150 foreach ($term_ancestors as $parent) {
151 $parent = get_term($parent, $term_taxonomy);
152 if(!empty($parent->slug)) {
153 $final_uri = $parent->slug . '/' . $final_uri;
154 }
155 }
156 }
157
158 $query[$query_parameter] = $final_uri;
159 } else {
160 $broken_uri = true;
161 }
162 }
163 /**
164 * 3B. Custom URI assigned to post/page/cpt item
165 */
166 else if(isset($element_id) && is_numeric($element_id)) {
167 // Fix for revisions
168 $is_revision = wp_is_post_revision($element_id);
169 $element_id = ($is_revision) ? $is_revision : $element_id;
170
171 // Filter detected post ID
172 $element_id = apply_filters('permalink-manager-detected-post-id', $element_id, $uri_parts);
173
174 $post_to_load = get_post($element_id);
175 $final_uri = (!empty($post_to_load->post_name)) ? $post_to_load->post_name : false;
176 $post_type = (!empty($post_to_load->post_type)) ? $post_to_load->post_type : false;
177
178 // Check if post type is allowed
179 $disabled = (Permalink_Manager_Helper_Functions::is_disabled($post_type, 'post_type')) ? true : false;
180
181 // Proceed only if the term is not removed and its taxonomy is not disabled
182 if(!$disabled && $post_type) {
183 // Fix for hierarchical CPT & pages
184 if(!(empty($post_to_load->ancestors))) {
185 foreach ($post_to_load->ancestors as $parent) {
186 $parent = get_post( $parent );
187 if($parent && $parent->post_name) {
188 $final_uri = $parent->post_name . '/' . $final_uri;
189 }
190 }
191 }
192
193 // Alter query parameters
194 if($post_type == 'page') {
195 $query['pagename'] = $final_uri;
196 } else if($post_type == 'post') {
197 $query['name'] = $final_uri;
198 } else if($post_type == 'attachment') {
199 $query['attachment'] = $final_uri;
200 } else {
201 // Get the query var
202 $post_type_object = get_post_type_object($post_type);
203 $query_var = (!empty($post_type_object->query_var)) ? $post_type_object->query_var : $post_type;
204
205 $query['name'] = $final_uri;
206 $query['post_type'] = $post_type;
207 $query[$query_var] = $final_uri;
208 }
209 } else {
210 $broken_uri = true;
211 }
212 }
213
214 /**
215 * 4. Auto-remove removed term custom URI & redirects (works if enabled in plugin settings)
216 */
217 if(!empty($broken_uri) && !empty($permalink_manager_options['general']['auto_remove_duplicates'])) {
218 $remove_broken_uri = Permalink_Manager_Actions::clear_single_element_uris_and_redirects($element_id);
219
220 // Reload page if success
221 if($remove_broken_uri) {
222 header("Refresh:0");
223 exit();
224 }
225 }
226
227 /**
228 * 5A. Endpoints
229 */
230 if($element_id && (!empty($endpoint)) || !empty($endpoint_value)) {
231 $endpoint = ($endpoint) ? str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint) : "page";
232
233 if($endpoint == 'feed') {
234 $query[$endpoint] = 'feed';
235 } elseif($endpoint == 'trackback') {
236 $query[$endpoint] = 1;
237 } else {
238 $query[$endpoint] = $endpoint_value;
239 }
240
241 // Fix for attachments
242 if(!empty($query['attachment'])) {
243 $query = array('attachment' => $query['attachment'], 'do_not_redirect' => 1);
244 }
245 }
246
247 /**
248 * 5B. Endpoints - check if any endpoint is set with $_GET parameter
249 */
250 if($deep_detect_enabled && !empty($_GET)) {
251 $get_endpoints = array_intersect($wp->public_query_vars, array_keys($_GET));
252
253 if(!empty($get_endpoints)) {
254 // Append query vars from $_GET parameters
255 foreach($get_endpoints as $endpoint) {
256 // Numeric endpoints
257 $endpoint_value = (in_array($endpoint, array('page', 'paged', 'attachment_id'))) ? filter_var($_GET[$endpoint], FILTER_SANITIZE_NUMBER_INT) : $_GET[$endpoint];
258 $query[$endpoint] = sanitize_text_field($endpoint_value);
259 }
260 }
261 }
262
263 /**
264 * 6. WWW prefix mismatch detect
265 */
266 $home_url_has_www = (strpos($raw_home_url, 'www.') !== false) ? true : false;
267 $requested_url_has_www = (strpos($_SERVER['HTTP_HOST'], 'www.') !== false) ? true : false;
268
269 if($home_url_has_www != $requested_url_has_www) {
270 unset($query['do_not_redirect']);
271 }
272
273 /**
274 * 7. Set global with detected item id
275 */
276 if(!empty($element_id)) {
277 $pm_item_id = $element_id;
278
279 // Make the redirects more clever - see new_uri_redirect_and_404() method
280 $query['do_not_redirect'] = 1;
281 }
282 }
283
284 /**
285 * 8. Debug mode
286 */
287 if(isset($_REQUEST['debug_url'])) {
288 $debug_info['old_query_vars'] = $old_query;
289 $debug_info['new_query_vars'] = $query;
290 $debug_info['detected_id'] = $pm_item_id;
291
292 $debug_txt = json_encode($debug_info);
293 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
294 wp_die($debug_txt);
295 }
296
297 return $query;
298 }
299
300 /**
301 * Trailing slash
302 */
303 function control_trailing_slashes($permalink) {
304 global $permalink_manager_options;
305
306 $trailing_slash_setting = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : "";
307
308 if(in_array($trailing_slash_setting, array(1, 10))) {
309 $permalink = trailingslashit($permalink);
310 } else if(in_array($trailing_slash_setting, array(2, 20))) {
311 $permalink = untrailingslashit($permalink);
312 }
313
314 return $permalink;
315 }
316
317 /**
318 * Display 404 if requested page does not exist in pagination
319 */
320 function fix_pagination_pages() {
321 global $wp_query;
322
323 // 1. Get the post object
324 $post = get_queried_object();
325
326 // 2. Check if post object is defined
327 if(empty($post->ID)) { return; }
328
329 // 3. Check if pagination is detected
330 if(empty($wp_query->query_vars['page'])) { return; }
331
332 // 4. Count post pages
333 $num_pages = substr_count(strtolower($post->post_content), '<!--nextpage-->') + 1;
334 if($wp_query->query_vars['page'] > $num_pages) {
335 $wp_query->set('p', null);
336 $wp_query->set('pagename', null);
337 $wp_query->set('page_id', null);
338 $wp_query->set_404();
339 }
340 }
341
342 /**
343 * Redirects
344 */
345 function new_uri_redirect_and_404() {
346 global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_options, $wp, $pm_item_id;
347
348 // Do not redirect on author pages & front page
349 if(is_author() || is_front_page() || is_home()) { return false; }
350
351 // Unset 404 if custom URI is detected
352 if(isset($pm_item_id)) {
353 $wp_query->is_404 = false;
354 }
355
356 // Sometimes $wp_query indicates the wrong object if requested directly
357 $queried_object = get_queried_object();
358
359 // Get the redirection mode & trailing slashes settings
360 $redirect_mode = (!empty($permalink_manager_options['general']['redirect'])) ? $permalink_manager_options['general']['redirect'] : false;
361 $trailing_slashes_mode = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : false;
362
363 // Get query string
364 $query_string = $_SERVER['QUERY_STRING'];
365
366 // Get home URL
367 $home_url = rtrim(get_option('home'), "/");
368
369 /**
370 * 1A. Custom redirects
371 */
372 if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request)) {
373 $uri = urldecode(trim($wp->request, "/ "));
374
375 // Filter endpoints
376 $endpoints = apply_filters("permalink-manager-endpoints", "page|feed|embed|attachment|track");
377 preg_match("/^(.+?)(?:\/($endpoints))?(?:\/([\d]+))?\/?$/i", $uri, $regex_parts);
378 $uri = (!empty($regex_parts[1])) ? $regex_parts[1] : $uri;
379
380 // Check if the URI is not assigned to any post/term's redirects
381 foreach($permalink_manager_redirects as $element => $redirects) {
382 if(is_array($redirects) && in_array($uri, $redirects)) {
383
384 // Post is detected
385 if(is_numeric($element)) {
386 $correct_permalink = get_permalink($element);
387 }
388 // Term is detected
389 else {
390 $term_id = intval(preg_replace("/[^0-9]/", "", $element));
391 $correct_permalink = get_term_link($term_id);
392 }
393 }
394 }
395 }
396
397 /**
398 * 1B. Enhance native redirect
399 */
400 if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) {
401 // Affect only posts with custom URI and old URIs
402 if(!empty($queried_object->ID) && isset($permalink_manager_uris[$queried_object->ID]) && empty($wp_query->query['preview'])) {
403 // Ignore posts with specific statuses
404 if(!(empty($queried_object->post_status)) && in_array($queried_object->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
405 return '';
406 }
407
408 // Check if post type is allowed
409 if(Permalink_Manager_Helper_Functions::is_disabled($queried_object->post_type, 'post_type')) { return ''; }
410
411 // Get the real URL
412 $correct_permalink = get_permalink($queried_object->ID);
413 }
414 // Affect only terms with custom URI and old URIs
415 else if(!empty($queried_object->term_id) && isset($permalink_manager_uris["tax-{$queried_object->term_id}"]) && defined('PERMALINK_MANAGER_PRO')) {
416 // Check if taxonomy is allowed
417 if(Permalink_Manager_Helper_Functions::is_disabled($queried_object->taxonomy, "taxonomy")) { return ''; }
418
419 // Get the real URL
420 $correct_permalink = get_term_link($queried_object->term_id, $queried_object->taxonomy);
421 }
422 }
423
424 /**
425 * 2. Check trailing slashes
426 */
427 if($trailing_slashes_mode) {
428 $home_dir = parse_url($home_url, PHP_URL_PATH);
429 $old_request = strtok($_SERVER['REQUEST_URI'], "?");
430
431 // Fix for WP installed in directories
432 $old_request = ltrim(str_replace($home_dir, "", $old_request), "/");
433 $ends_with_slash = (substr($old_request, -1) == "/") ? true : false;
434
435 // Homepage should be ignored
436 if($old_request != "/") {
437 // 2A. Force trailing slashes
438 if($trailing_slashes_mode == 10 && $ends_with_slash == false) {
439 $correct_permalink = (!empty($correct_permalink)) ? "{$correct_permalink}/" : "{$home_url}/{$old_request}/";
440 }
441 // 2B. Remove trailing slashes
442 else if($trailing_slashes_mode == 20 && $ends_with_slash == true) {
443 $correct_permalink = (!empty($correct_permalink)) ? $correct_permalink : "{$home_url}/{$old_request}";
444 $correct_permalink = trim($correct_permalink, "/");
445 }
446 }
447 }
448
449 /**
450 * 3. Ignore default URIs (or do nothing if redirects are disabled)
451 */
452 if(!empty($correct_permalink) && !empty($redirect_mode)) {
453 // Append query string
454 $correct_permalink = (!empty($query_string)) ? "{$correct_permalink}?{$query_string}" : $correct_permalink;
455
456 wp_safe_redirect($correct_permalink, $redirect_mode);
457 exit();
458 }
459 }
460
461 function adjust_canonical_redirect() {
462 global $permalink_manager_options, $permalink_manager_uris, $wp, $wp_rewrite;
463
464 // Adjust rewrite settings for trailing slashes
465 $trailing_slash_setting = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : "";
466 if(in_array($trailing_slash_setting, array(1, 10))) {
467 $wp_rewrite->use_trailing_slashes = true;
468 } else if(in_array($trailing_slash_setting, array(2, 20))) {
469 $wp_rewrite->use_trailing_slashes = false;
470 }
471
472 // Get endpoints
473 $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
474 $endpoints_array = ($endpoints) ? explode("|", $endpoints) : array();
475
476 // Check if any endpoint is called (fix for feed and similar endpoints)
477 foreach($endpoints_array as $endpoint) {
478 if(!empty($wp->query_vars[$endpoint])) {
479 $wp->query_vars['do_not_redirect'] = 1;
480 break;
481 }
482 }
483
484 // Do nothing for posts and terms without custom URIs (when canonical redirect is enabled)
485 $element = get_queried_object();
486 if(!empty($element->ID)) {
487 $custom_uri = (!empty($permalink_manager_uris[$element->ID])) ? $permalink_manager_uris[$element->ID] : "";
488 } else if(!empty($element->term_id)) {
489 $custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : "";
490 }
491
492 if(empty($custom_uri) && !empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
493
494 if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) {
495 remove_action('template_redirect', 'redirect_canonical');
496 add_filter('wpml_is_redirected', '__return_false', 99, 2);
497 }
498 }
499
500 /**
501 * Case insensitive permalinks
502 */
503 function case_insensitive_permalinks() {
504 global $permalink_manager_options, $permalink_manager_uris;
505
506 if(!empty($permalink_manager_options['general']['case_insensitive_permalinks']) && !empty($_SERVER['REQUEST_URI'])) {
507 $_SERVER['REQUEST_URI'] = strtolower($_SERVER['REQUEST_URI']);
508 $permalink_manager_uris = array_map('strtolower', $permalink_manager_uris);
509 }
510 }
511
512 }
513