Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- * Plugin Name: Post Permalinks Rewrite
- * Plugin URI: http://maciejbis.net/
- * Description: Plugin that allows to keep custom permalinks format in Wordpress
- * Version: 1.0.0
- * Author: Maciej Bis
- * Author URI: http://maciejbis.net/
- * License: GPL-2.0+
- * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
- * Domain Path: /languages
- */
- /**
- * Get a list of filtered post types
- */
- function bis_get_post_types($post_type = null) {
- $post_types = array(
- 'post' => '%category%/%postname%',
- );
- return ($post_type && !empty($post_types[$post_type])) ? $post_types[$post_type] : $post_types;
- }
- /**
- * Filter product & taxonomies permalinks
- */
- function bis_filter_custom_permalinks($url, $element) {
- // Posts permalinks added after this date will be changed
- if(strtotime($element->post_date) <= strtotime('2019-07-09')) {
- return $url;
- }
- $post_types = bis_get_post_types();
- $home_base = trim(get_option('home'), '/');
- if(!empty($element->post_type) && (!empty($post_types[$element->post_type]))) {
- $uris = bis_get_uris($element->post_type);
- $uri = (!empty($uris[$element->ID])) ? $uris[$element->ID] : false;
- // Try to add the URI if it was not found
- if(empty($uri)) {
- $uri = bis_flush_single_uri($element);
- }
- $url = ($uri) ? "{$home_base}/{$uri}" : $url;
- }
- return user_trailingslashit($url);
- }
- add_filter('post_link', 'bis_filter_custom_permalinks', 999, 2);
- function bis_unlimited_permalinks($request) {
- global $wpdb, $wp;
- if(!empty($request['pagename']) || !empty($request['name']) || !empty($request['error'])) {
- if(!empty($request['pagename'])) {
- $name = $request['pagename'];
- } else if(!empty($request['name'])) {
- $name = $request['name'];
- } else {
- $name = $wp->request;
- }
- $post_name = basename($name);
- $element = $wpdb->get_row($wpdb->prepare("
- SELECT * FROM {$wpdb->posts}
- WHERE post_name = %s
- AND post_status = 'publish'
- ",
- $post_name
- ));
- if($element->post_name && $element->post_type == 'post') {
- unset($request['pagename']);
- unset($request['error']);
- $request['name'] = $post_name;
- $request['do_not_redirect'] = true;
- // Disable canonical redirect
- remove_action('template_redirect', 'redirect_canonical');
- add_filter('wpml_is_redirected', '__return_false', 99, 2);
- }
- }
- return $request;
- }
- add_filter('request', 'bis_unlimited_permalinks', 999);
- /**
- * Get post term
- */
- function bis_get_post_term_slug($post_id, $taxonomy) {
- $slug = '';
- // Try to use Yoast's SEO primary term
- if(class_exists('WPSEO_Primary_Term')) {
- $primary_term = new WPSEO_Primary_Term($taxonomy, $post_id);
- $primary_term = get_term($primary_term->get_primary_term());
- }
- if(empty($primary_term->term_id)) {
- $terms = wp_get_object_terms($post_id, $taxonomy);
- $primary_term = (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) ? bis_get_lowest_term($terms[0], $terms) : "";
- }
- // No term was found
- if(empty($primary_term->term_id)) {
- return;
- }
- // Get slug
- $full_slug = $primary_term->slug;
- // Support hierarchical taxonomies
- if(!empty($primary_term->parent)) {
- $term = $primary_term;
- while(!is_wp_error($term) && !empty($term->parent)) {
- $term = get_term($term->parent, $taxonomy);
- $full_slug = "{$term->slug}/{$full_slug}";
- }
- }
- return $full_slug;
- }
- /**
- * Get lowest level term/post
- */
- function bis_get_lowest_term($first_element, $elements) {
- if(!empty($elements) && !empty($first_element)) {
- // Get the ID of first element
- if(!empty($first_element->term_id)) {
- $first_element_id = $first_element->term_id;
- $parent_key = 'parent';
- } else {
- return false;
- }
- $children = wp_filter_object_list($elements, array($parent_key => $first_element_id));
- if(!empty($children)) {
- // Get the first term
- $child_term = reset($children);
- $first_element = bis_get_lowest_term($child_term, $elements);
- }
- }
- return $first_element;
- }
- /**
- * Cache slugs to avoid extra SQL queries
- */
- function bis_get_uris($post_type = null, $fix_uris = false) {
- global $wpdb;
- // 1. Try to use transient
- $transient_name = "bis_slugs_posts_{$post_type}";
- $slugs = (array) get_transient($transient_name);
- if(empty($slugs) || $fix_uris) {
- $results = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = '{$post_type}' AND post_status = 'publish'");
- // Omit defined URIs
- if($fix_uris) {
- $ignore_ids = array_keys($slugs);
- $results = array_diff($results, $ignore_ids);
- }
- // Schedule URI regenerate and split into chunks (if there are more than 1000 posts)
- if(count($results) > 1000) {
- $chunks = array_chunk($results, 250);
- foreach($chunks as $i => $chunk) {
- if($i == 0) {
- bis_flush_uris($chunk, $post_type);
- } else {
- wp_schedule_single_event(time() + ($i * 60), 'bis_flush_uris_hook', array($chunk, $post_type));
- }
- }
- } else {
- bis_flush_uris($results, $post_type);
- }
- }
- return $slugs;
- }
- /**
- * Prepare URIs
- */
- function bis_flush_uris($posts, $post_type) {
- $transient_name = "bis_slugs_posts_{$post_type}";
- $slugs = get_transient($transient_name);
- $slugs = (is_array($slugs)) ? $slugs : array();
- // Parse the results - ID -> URI
- foreach($posts as $post_id) {
- $slugs[$post_id] = bis_get_post_custom_uri($post_id, $post_type);
- }
- set_transient($transient_name, array_filter($slugs));
- }
- add_action('bis_flush_uris_hook', 'bis_flush_uris', 9, 2);
- /**
- * Flush slugs when product, category or tag is added/edited or removed
- */
- function bis_flush_single_uri_init() {
- add_action('wp_insert_post', 'bis_flush_single_uri', 9);
- add_action('wp_trash_post', 'bis_flush_single_uri', 9);
- add_action('save_post', 'bis_flush_single_uri', 9);
- // Support REST API
- $post_types = bis_get_post_types();
- foreach($post_types as $post_type => $structure) {
- add_action("rest_after_insert_{$post_type}", 'bis_flush_single_uri', 9);
- }
- }
- add_action('init', 'bis_flush_single_uri_init');
- function bis_flush_single_uri($post) {
- $post = (!empty($post->ID)) ? $post : get_post($post);
- $uri = null;
- if(!empty($post->post_type)) {
- $transient_name = "bis_slugs_posts_{$post->post_type}";
- $slugs = (array) get_transient($transient_name);
- // Set new URI for new post
- $slugs[$post->ID] = $uri = bis_get_post_custom_uri($post->ID, $post->post_type);
- set_transient($transient_name, $slugs);
- return $uri;
- }
- }
- /**
- * Get single post custom URI
- */
- function bis_get_post_custom_uri($post_id, $post_type) {
- // Get full slug
- $slug = get_page_uri($post_id);
- // Get permalink format
- $uri_format = bis_get_post_types($post_type);
- // Stop if the format is not a string
- if(is_array($uri_format)) { return; }
- // Add post slug
- $uri = str_replace('%postname%', $slug, $uri_format);
- // Add taxonomy tags
- preg_match_all("/%(.[^\%]+)%/", $uri, $taxonomy_tags);
- if(!empty($taxonomy_tags[1])) {
- foreach($taxonomy_tags[1] as $taxonomy) {
- $term_slug = bis_get_post_term_slug($post_id, $taxonomy);
- $uri = ($term_slug) ? str_replace("%{$taxonomy}%", $term_slug, $uri) : $uri;
- }
- }
- return $uri;
- }
- /**
- * Debug transients
- */
- function bis_debug_slugs() {
- // if(!is_user_logged_in()) { return; }
- if(isset($_GET['debug_uris'])) {
- $uris = (array) bis_get_uris($_GET['debug_uris']);
- print_r($uris);
- die();
- }
- if(isset($_GET['fix_uris'])) {
- $uris = (array) bis_get_uris($_GET['fix_uris'], true);
- print_r($uris);
- die();
- }
- if(!empty($_GET['flush_uris'])) {
- $post_type = sanitize_text_field($_GET['flush_uris']);
- delete_transient("bis_slugs_posts_{$post_type}");
- $uris = (array) bis_get_uris($_GET['debug_uris']);
- print_r($uris);
- die();
- }
- }
- add_action('init', 'bis_debug_slugs', 999);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement