mbis

Detect Permalink Manager custom permalinks

Mar 18th, 2020 (edited)
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.45 KB | None | 0 0
  1. function pm_detect_post($query) {
  2.     global $wpdb, $wp, $wp_rewrite, $wp_filter;
  3.  
  4.     $permalink_manager_uris = get_option('permalink-manager-uris');
  5.  
  6.     // Check if the array with custom URIs is set
  7.     if(!(is_array($permalink_manager_uris))) return $query;
  8.  
  9.     // Used in debug mode & endpoints
  10.     $old_query = $query;
  11.  
  12.     /**
  13.     * 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)
  14.     */
  15.     $request_url = (!empty($request_url)) ? parse_url($request_url, PHP_URL_PATH) : $_SERVER['REQUEST_URI'];
  16.     $request_url = strtok($request_url, "?");
  17.  
  18.     $http_host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : preg_replace('/www\./i', '', $_SERVER['SERVER_NAME']);
  19.     $request_url = sprintf("http://%s%s", str_replace("www.", "", $http_host), $request_url);
  20.     $raw_home_url = trim(get_option('home'));
  21.     $home_url = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $raw_home_url);
  22.  
  23.     if(filter_var($request_url, FILTER_VALIDATE_URL)) {
  24.         // Check if "Deep Detect" is enabled
  25.         $deep_detect_enabled = 1
  26.  
  27.         // Sanitize the URL
  28.         // $request_url = filter_var($request_url, FILTER_SANITIZE_URL);
  29.  
  30.         // Keep only the URI
  31.         $request_url = str_replace($home_url, "", $request_url);
  32.  
  33.         // Hotfix for language plugins
  34.         if(filter_var($request_url, FILTER_VALIDATE_URL)) {
  35.             $request_url = parse_url($request_url, PHP_URL_PATH);
  36.         }
  37.  
  38.         $request_url = trim($request_url, "/");
  39.  
  40.         // Get all the endpoints & pattern
  41.         $endpoints = 'page|feed|embed|attachment|trackback|filter';
  42.         $pattern = "/^(.+?)(?|\/({$endpoints})(?|\/(.*)|$)|\/()([\d]+)\/?)?$/i";
  43.  
  44.         // Use default REGEX to detect post
  45.         preg_match($pattern, $request_url, $regex_parts);
  46.         $uri_parts['lang'] = false;
  47.         $uri_parts['uri'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
  48.         $uri_parts['endpoint'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
  49.         $uri_parts['endpoint_value'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
  50.  
  51.         // Allow to filter the results by third-parties + store the URI parts with $pm_query global
  52.         $uri_parts = $pm_query = apply_filters('permalink_manager_detect_uri', $uri_parts, $request_url, $endpoints);
  53.  
  54.         // Support comment pages
  55.         preg_match("/(.*)\/{$wp_rewrite->comments_pagination_base}-([\d]+)/", $request_url, $regex_parts);
  56.         if(!empty($regex_parts[2])) {
  57.             $uri_parts['uri'] = $regex_parts[1];
  58.             $uri_parts['endpoint'] = 'cpage';
  59.             $uri_parts['endpoint_value'] = $regex_parts[2];
  60.         }
  61.  
  62.         // Support pagination endpoint
  63.         if($uri_parts['endpoint'] == $wp_rewrite->pagination_base) {
  64.             $uri_parts['endpoint'] = 'page';
  65.         }
  66.  
  67.         // Stop the function if $uri_parts is empty
  68.         if(empty($uri_parts)) return $query;
  69.  
  70.         // Get the URI parts from REGEX parts
  71.         $lang = $uri_parts['lang'];
  72.         $uri = $uri_parts['uri'];
  73.         $endpoint = $uri_parts['endpoint'];
  74.         $endpoint_value = $uri_parts['endpoint_value'];
  75.  
  76.         // Trim slashes
  77.         $uri = trim($uri, "/");
  78.  
  79.         // Ignore URLs with no URI grabbed
  80.         if(empty($uri)) return $query;
  81.  
  82.         // Store an array with custom permalinks in a separate variable
  83.         $all_uris = $permalink_manager_uris;
  84.  
  85.         // Check what content type should be loaded in case of duplicate ("posts" or "terms")
  86.         $duplicates_priority = apply_filters('permalink_manager_duplicates_priority', false);
  87.         if($duplicates_priority !== false) {
  88.             $uri_count = array_count_values($all_uris);
  89.  
  90.             foreach($uri_count as $duplicated_uri => $count) {
  91.                 if($count <= 1) { continue; }
  92.  
  93.                 $duplicates_ids = array_keys($all_uris, $duplicated_uri);
  94.  
  95.                 foreach($duplicates_ids as $id) {
  96.                     if($duplicates_priority == 'posts' && !is_numeric($id)) {
  97.                         unset($all_uris[$id]);
  98.                     } else if($duplicates_priority !== 'posts' && is_numeric($id)) {
  99.                         unset($all_uris[$id]);
  100.                     }
  101.                 }
  102.             }
  103.         }
  104.  
  105.         // Flip array for better performance
  106.         $all_uris = array_flip($all_uris);
  107.  
  108.         // Attempt 1.
  109.         // Find the element ID
  110.         $element_id = isset($all_uris[$uri]) ? $all_uris[$uri] : false;
  111.  
  112.         // Atempt 2.
  113.         // Decode both request URI & URIs array & make them lowercase (and save in a separate variable)
  114.         if(empty($element_id)) {
  115.             $uri = strtolower(urldecode($uri));
  116.  
  117.             foreach($all_uris as $raw_uri => $uri_id) {
  118.                 $raw_uri = urldecode($raw_uri);
  119.                 $all_uris[$raw_uri] = $uri_id;
  120.             }
  121.  
  122.             // Convert array keys lowercase
  123.             $all_uris = array_change_key_case($all_uris, CASE_LOWER);
  124.  
  125.             $element_id = isset($all_uris[$uri]) ? $all_uris[$uri] : $element_id;
  126.         }
  127.  
  128.         // Atempt 3.
  129.         // Check again in case someone used post/tax IDs instead of slugs
  130.         if($deep_detect_enabled && is_numeric($endpoint_value) && isset($all_uris["{$uri}/{$endpoint_value}"])) {
  131.             $element_id = $all_uris["{$uri}/{$endpoint_value}"];
  132.             $endpoint_value = $endpoint = "";
  133.         }
  134.  
  135.         // Atempt 4.
  136.         // Check again for attachment custom URIs
  137.         if(empty($element_id) && isset($old_query['attachment'])) {
  138.             $element_id = isset($all_uris["{$uri}/{$endpoint}/{$endpoint_value}"]) ? $all_uris["{$uri}/{$endpoint}/{$endpoint_value}"] : $element_id;
  139.  
  140.             if($element_id) {
  141.                 $endpoint_value = $endpoint = "";
  142.             }
  143.         }
  144.  
  145.         // Allow to filter the item_id by third-parties after initial detection
  146.         $element_id = apply_filters('permalink_manager_detected_element_id', $element_id, $uri_parts, $request_url);
  147.  
  148.         // Clear the original query before it is filtered
  149.         $query = ($element_id) ? array() : $query;
  150.  
  151.         /**
  152.         * 3A. Custom URI assigned to taxonomy
  153.         */
  154.         if(strpos($element_id, 'tax-') !== false) {
  155.             // Remove the "tax-" prefix
  156.             $term_id = intval(preg_replace("/[^0-9]/", "", $element_id));
  157.  
  158.             // Filter detected post ID
  159.             $term_id = apply_filters('permalink_manager_detected_term_id', intval($term_id), $uri_parts, true);
  160.  
  161.             // Get the variables to filter wp_query and double-check if taxonomy exists
  162.             $term = get_term($term_id);
  163.             $term_taxonomy = (!empty($term->taxonomy)) ? $term->taxonomy : false;
  164.  
  165.             // Proceed only if the term is not removed and its taxonomy is not disabled
  166.             if(!$disabled && $term_taxonomy) {
  167.                 // Get some term data
  168.                 if($term_taxonomy == 'category') {
  169.                     $query_parameter = 'category_name';
  170.                 } else if($term_taxonomy == 'post_tag') {
  171.                     $query_parameter = 'tag';
  172.                 } else {
  173.                     $query["taxonomy"] = $term_taxonomy;
  174.                     $query_parameter = $term_taxonomy;
  175.                 }
  176.                 $term_ancestors = get_ancestors($term_id, $term_taxonomy);
  177.                 $final_uri = $term->slug;
  178.  
  179.                 // Fix for hierarchical terms
  180.                 if(!empty($term_ancestors)) {
  181.                     foreach ($term_ancestors as $parent_id) {
  182.                         $parent = get_term((int) $parent_id, $term_taxonomy);
  183.                         if(!empty($parent->slug)) {
  184.                             $final_uri = $parent->slug . '/' . $final_uri;
  185.                         }
  186.                     }
  187.                 }
  188.  
  189.                 //$query["term"] = $final_uri;
  190.                 $query["term"] = $term->slug;
  191.                 //$query[$query_parameter] = $final_uri;
  192.                 $query[$query_parameter] = $term->slug;
  193.             } else {
  194.                 $broken_uri = true;
  195.             }
  196.         }
  197.         /**
  198.         * 3B. Custom URI assigned to post/page/cpt item
  199.         */
  200.         else if(isset($element_id) && is_numeric($element_id)) {
  201.             // Fix for revisions
  202.             $is_revision = wp_is_post_revision($element_id);
  203.             if($is_revision) {
  204.                 $revision_id = $element_id;
  205.                 $element_id = $is_revision;
  206.             }
  207.  
  208.             // Filter detected post ID
  209.             $element_id = apply_filters('permalink_manager_detected_post_id', $element_id, $uri_parts);
  210.  
  211.             $post_to_load = get_post($element_id);
  212.             $final_uri = (!empty($post_to_load->post_name)) ? $post_to_load->post_name : false;
  213.             $post_type = (!empty($post_to_load->post_type)) ? $post_to_load->post_type : false;
  214.  
  215.             // Proceed only if the term is not removed and its taxonomy is not disabled
  216.             if(!$disabled && $post_type) {
  217.                 $post_type_object = get_post_type_object($post_type);
  218.  
  219.                 // Fix for hierarchical CPT & pages
  220.                 if(!(empty($post_to_load->ancestors)) && !empty($post_type_object->hierarchical)) {
  221.                     foreach ($post_to_load->ancestors as $parent) {
  222.                         $parent = get_post( $parent );
  223.                         if($parent && $parent->post_name) {
  224.                             $final_uri = $parent->post_name . '/' . $final_uri;
  225.                         }
  226.                     }
  227.                 }
  228.  
  229.                 // Alter query parameters + support drafts URLs
  230.                 if($post_to_load->post_status == 'draft' || empty($final_uri)) {
  231.                     if(is_user_logged_in()) {
  232.                         $query['p'] = $element_id;
  233.                         $query['preview'] = true;
  234.                         $query['post_type'] = $post_type;
  235.                     } else if($post_to_load->post_status == 'draft') {
  236.                         $query['pagename'] = '-';
  237.                         $query['error'] = '404';
  238.  
  239.                         $element_id = 0;
  240.                     } else {
  241.                         $query = $old_query;
  242.                     }
  243.                 } else if($post_type == 'page') {
  244.                     $query['pagename'] = $final_uri;
  245.                     // $query['post_type'] = $post_type;
  246.                 } else if($post_type == 'post') {
  247.                     $query['name'] = $final_uri;
  248.                 } else if($post_type == 'attachment') {
  249.                     $query['attachment'] = $final_uri;
  250.                 } else {
  251.                     // Get the query var
  252.                     $query_var = (!empty($post_type_object->query_var)) ? $post_type_object->query_var : $post_type;
  253.  
  254.                     $query['name'] = $final_uri;
  255.                     $query['post_type'] = $post_type;
  256.                     $query[$query_var] = $final_uri;
  257.                 }
  258.             } else {
  259.                 $broken_uri = true;
  260.             }
  261.         }
  262.  
  263.         /**
  264.         * 5A. Endpoints
  265.         */
  266.         if(!empty($element_id) && (!empty($endpoint) || !empty($endpoint_value))) {
  267.             if(is_array($endpoint)) {
  268.                 foreach($endpoint as $endpoint_name => $endpoint_value) {
  269.                     $query[$endpoint_name] = $endpoint_value;
  270.                 }
  271.             } else if($endpoint == 'feed') {
  272.                 $query[$endpoint] = 'feed';
  273.             } else if($endpoint == 'page') {
  274.                 $endpoint = 'paged';
  275.                 $query[$endpoint] = $endpoint_value;
  276.             } else if($endpoint == 'trackback') {
  277.                 $endpoint = 'tb';
  278.                 $query[$endpoint] = 1;
  279.             } else if(!$endpoint && is_numeric($endpoint_value)) {
  280.                 $query['page'] = $endpoint_value;
  281.             } else {
  282.                 $query[$endpoint] = $endpoint_value;
  283.             }
  284.  
  285.             // Fix for attachments
  286.             if(!empty($query['attachment'])) {
  287.                 $query = array('attachment' => $query['attachment'], 'do_not_redirect' => 1);
  288.             }
  289.         }
  290.  
  291.         /**
  292.          * 6. Set global with detected item id
  293.          */
  294.         if(!empty($element_id)) {
  295.             $pm_query['id'] = $element_id;
  296.  
  297.             // Make the redirects more clever
  298.             $query['do_not_redirect'] = 1;
  299.  
  300.             /**
  301.              * Disable canonical redirect
  302.              */
  303.             remove_action('template_redirect', 'redirect_canonical');
  304.             add_filter('wpml_is_redirected', '__return_false', 99, 2);
  305.             add_filter('pll_check_canonical_url', '__return_false', 99, 2);
  306.             remove_action('template_redirect', 'wp_old_slug_redirect');
  307.         }
  308.     }
  309.  
  310.     return $query;
  311. }
  312. add_filter('request', 'pm_detect_post', 0, 1);
Add Comment
Please, Sign In to add comment