permalink-manager
Last commit date
css
9 years ago
includes
9 years ago
js
9 years ago
languages
9 years ago
out
9 years ago
LICENSE.txt
9 years ago
README.txt
9 years ago
permalink-manager.php
9 years ago
permalink-manager.php
277 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Plugin Name: Permalink Manager |
| 5 | * Plugin URI: http://maciejbis.net/ |
| 6 | * Description: A simple tool that allows to mass update of slugs that are used to build permalinks for Posts, Pages and Custom Post Types. |
| 7 | * Version: 0.5.4 |
| 8 | * Author: Maciej Bis |
| 9 | * Author URI: http://maciejbis.net/ |
| 10 | * License: GPL-2.0+ |
| 11 | * License URI: http://www.gnu.org/licenses/gpl-2.0.txt |
| 12 | * Text Domain: permalink-manager |
| 13 | * Domain Path: /languages |
| 14 | */ |
| 15 | // If this file is called directly, abort. |
| 16 | if ( ! defined( 'WPINC' ) ) { |
| 17 | die; |
| 18 | } |
| 19 | |
| 20 | // Define the directories used to load plugin files. |
| 21 | define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' ); |
| 22 | define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' ); |
| 23 | define( 'PERMALINK_MANAGER_VERSION', '0.5.4' ); |
| 24 | define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) ); |
| 25 | define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) ); |
| 26 | define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) ); |
| 27 | define( 'PERMALINK_MANAGER_WEBSITE', 'http://maciejbis.net' ); |
| 28 | |
| 29 | class Permalink_Manager_Class { |
| 30 | |
| 31 | public $permalink_manager, $permalink_manager_options_page, $permalink_manager_options; |
| 32 | public $sections, $functions, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html; |
| 33 | |
| 34 | /** |
| 35 | * Get options from DB, load subclasses & hooks |
| 36 | */ |
| 37 | public function __construct() { |
| 38 | $this->include_subclassess(); |
| 39 | $this->run_subclasses(); |
| 40 | $this->register_init_hooks(); |
| 41 | } |
| 42 | |
| 43 | /** |
| 44 | * Include back-end classess and set their instances |
| 45 | */ |
| 46 | function include_subclassess() { |
| 47 | // Load back-end functions |
| 48 | foreach(array('helper-functions', 'post-uri-functions', 'admin-functions', 'uri-actions') as $class) { |
| 49 | require_once PERMALINK_MANAGER_DIR . "/includes/core/permalink-manager-{$class}.php"; |
| 50 | } |
| 51 | |
| 52 | // WP_List_Table needed for post types & taxnomies editors |
| 53 | if( ! class_exists( 'WP_List_Table' ) ) { |
| 54 | require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); |
| 55 | } |
| 56 | |
| 57 | // Load section classes |
| 58 | foreach(array('uri-editor', 'tools', 'permastructs', 'settings', 'advanced') as $class) { |
| 59 | require_once PERMALINK_MANAGER_DIR . "/includes/views/permalink-manager-{$class}.php"; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | /** |
| 64 | * Load front-end classes and set their instances. |
| 65 | */ |
| 66 | function run_subclasses() { |
| 67 | $this->functions['helper_functions'] = new Permalink_Manager_Helper_Functions(); |
| 68 | $this->functions['admin_functions'] = new Permalink_Manager_Admin_Functions(); |
| 69 | $this->functions['post_uri_functions'] = new Permalink_Manager_Post_URI_Functions(); |
| 70 | $this->functions['uri_actions'] = new Permalink_Manager_Uri_Actions(); |
| 71 | $this->sections['uri_editor'] = new Permalink_Manager_Uri_Editor(); |
| 72 | $this->sections['tools'] = new Permalink_Manager_Tools(); |
| 73 | $this->sections['permastructs'] = new Permalink_Manager_Permastructs(); |
| 74 | $this->sections['settings'] = new Permalink_Manager_Settings(); |
| 75 | $this->sections['advanced'] = new Permalink_Manager_Advanced(); |
| 76 | } |
| 77 | |
| 78 | /** |
| 79 | * Register general hooks |
| 80 | */ |
| 81 | public function register_init_hooks() { |
| 82 | // Localize plugin |
| 83 | add_action( 'plugins_loaded', array($this, 'localize_me'), 1 ); |
| 84 | |
| 85 | // Load options |
| 86 | add_action( 'init', array($this, 'get_options_and_globals'), 1 ); |
| 87 | |
| 88 | // Use the URIs set in this plugin + redirect from old URIs to new URIs + adjust canonical redirect settings |
| 89 | add_action( 'wp', array($this, 'disable_canonical_redirect'), 0, 1 ); |
| 90 | add_action( 'template_redirect', array($this, 'redirect_to_new_uri'), 999); |
| 91 | add_filter( 'request', array($this, 'detect_post'), 0, 1 ); |
| 92 | } |
| 93 | |
| 94 | /** |
| 95 | * Localize this plugin |
| 96 | */ |
| 97 | function localize_me() { |
| 98 | load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR ); |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Get options values & set global |
| 103 | */ |
| 104 | public function get_options_and_globals() { |
| 105 | // 1. Globals with data stored in DB |
| 106 | global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs; |
| 107 | |
| 108 | $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager')); |
| 109 | $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris')); |
| 110 | $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs')); |
| 111 | |
| 112 | // 2. Globals used to display additional content (eg. alerts) |
| 113 | global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html; |
| 114 | |
| 115 | $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', ''); |
| 116 | $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', ''); |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin |
| 121 | */ |
| 122 | function detect_post($query) { |
| 123 | global $wpdb, $permalink_manager_uris; |
| 124 | |
| 125 | // Used in debug mode |
| 126 | $old_query = $query; |
| 127 | |
| 128 | $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://'; |
| 129 | $url = str_replace(home_url(), "{$protocol}{$_SERVER['HTTP_HOST']}", "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); // Fix for Wordpress installed in subdirectories |
| 130 | |
| 131 | // Remove .html suffix from URL and query (URLs ended with .html work as aliases) |
| 132 | $url = str_replace(".html", "", $url); |
| 133 | if(isset($query['name'])) { $query['name'] = str_replace('.html', '', $query['name']); } |
| 134 | if(isset($query['pagename'])) { $query['pagename'] = str_replace('.html', '', $query['pagename']); } |
| 135 | |
| 136 | // Check if it is correct URL |
| 137 | if (filter_var($url, FILTER_VALIDATE_URL)) { |
| 138 | // Separate endpoints (if set) - support for comment pages will be added later |
| 139 | preg_match("/(.*)\/(page|feed|embed|attachment|track)\/(.*)/", $url, $url_with_endpoints); |
| 140 | if(isset($url_with_endpoints[3]) && !(empty($url_with_endpoints[3]))) { |
| 141 | $url = $url_with_endpoints[1]; |
| 142 | $endpoint = str_replace(array('page', 'trackback'), array('paged', 'tb'), $url_with_endpoints[2]); |
| 143 | $endpoint_value = $url_with_endpoints[3]; |
| 144 | } |
| 145 | |
| 146 | // Parse URL |
| 147 | $url_parts = parse_url($url); |
| 148 | $uri = (isset($url_parts['path'])) ? trim($url_parts['path'], "/") : ""; |
| 149 | if(empty($uri)) return $query; |
| 150 | |
| 151 | // Check if current URL is assigned to any post |
| 152 | if(!(is_array($permalink_manager_uris))) return $query; |
| 153 | $post_id = array_search($uri, $permalink_manager_uris); |
| 154 | |
| 155 | // Check again in case someone added .html suffix to particular post (with .html suffix) |
| 156 | $post_id = (empty($post_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $post_id; |
| 157 | |
| 158 | if(isset($post_id) && is_numeric($post_id)) { |
| 159 | // Check if it is revision (hotfix) and use original post ID instead of revision ID |
| 160 | $is_revision = wp_is_post_revision($post_id); |
| 161 | |
| 162 | // Debug for @andresgl |
| 163 | if(isset($_REQUEST['debug_detect_post'])) { |
| 164 | $post_to_load = (is_object(get_post($post_id))) ? get_post($post_id) : 'no object!'; |
| 165 | $revision_post_to_load = (is_object(get_post($is_revision))) ? get_post($is_revision) : 'no object!'; |
| 166 | |
| 167 | $debug_array = array( |
| 168 | 'original_post_id' => $post_id, |
| 169 | 'original_post' => $post_to_load, |
| 170 | 'revision_post_id' => $is_revision, |
| 171 | 'revision_post' => $revision_post_to_load, |
| 172 | ); |
| 173 | |
| 174 | wp_die("<pre>" . print_r($debug_array, true) . "</pre>"); |
| 175 | } |
| 176 | |
| 177 | $post_id = ($is_revision) ? $is_revision : $post_id; |
| 178 | |
| 179 | $post_to_load = get_post($post_id); |
| 180 | $original_page_uri = $post_to_load->post_name; |
| 181 | $post_type = $post_to_load->post_type; |
| 182 | unset($query['attachment']); |
| 183 | unset($query['error']); |
| 184 | |
| 185 | // Fix for hierarchical CPT & pages |
| 186 | if( isset($post_to_load->ancestors) && !(empty($post_to_load->ancestors))) { |
| 187 | foreach ( $post_to_load->ancestors as $parent ) { |
| 188 | $parent = get_post( $parent ); |
| 189 | if ( $parent && $parent->post_name ) { |
| 190 | $original_page_uri = $parent->post_name . '/' . $original_page_uri; |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | // Fix for not-pages |
| 196 | if($post_to_load->post_type != 'post') { |
| 197 | unset($query['year']); |
| 198 | unset($query['monthnum']); |
| 199 | unset($query['day']); |
| 200 | } |
| 201 | |
| 202 | // Alter query parameters |
| 203 | if($post_to_load->post_type == 'page') { |
| 204 | unset($query['name']); |
| 205 | $query['pagename'] = $original_page_uri; |
| 206 | } else if($post_to_load->post_type == 'post') { |
| 207 | $query['name'] = $original_page_uri; |
| 208 | } else { |
| 209 | $query['name'] = $original_page_uri; |
| 210 | $query['post_type'] = $post_type; |
| 211 | $query[$post_type] = $original_page_uri; |
| 212 | } |
| 213 | |
| 214 | // Make the redirects more clever - see redirect_to_new_uri() method |
| 215 | $query['do_not_redirect'] = 1; |
| 216 | |
| 217 | // Add endpoint |
| 218 | if(isset($endpoint_value) && !(empty($endpoint_value))) { |
| 219 | $query[$endpoint] = $endpoint_value; |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | // Debug mode |
| 225 | if(isset($_REQUEST['debug_url'])) { |
| 226 | $debug_info['old_query_vars'] = $old_query; |
| 227 | $debug_info['new_query_vars'] = $query; |
| 228 | //$debug_info['request'] = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; |
| 229 | $debug_info['request'] = $url; |
| 230 | |
| 231 | $debug_txt = json_encode($debug_info); |
| 232 | $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>"; |
| 233 | wp_die($debug_txt); |
| 234 | } |
| 235 | |
| 236 | return $query; |
| 237 | } |
| 238 | |
| 239 | function redirect_to_new_uri() { |
| 240 | global $wp, $wp_query, $permalink_manager_uris, $permalink_manager_options; |
| 241 | |
| 242 | // Affect only posts with custom URI and old URIs |
| 243 | if(is_singular() && isset($permalink_manager_uris[$wp_query->queried_object_id]) && empty($wp_query->query['do_not_redirect'])) { |
| 244 | $current_url = home_url(add_query_arg(array(),$wp->request)); |
| 245 | $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($wp_query->queried_object_id, true); |
| 246 | |
| 247 | $active_permalink = str_replace($native_uri, $permalink_manager_uris[$wp_query->queried_object_id], $current_url); |
| 248 | } |
| 249 | |
| 250 | // Get the redirection mode |
| 251 | $redirect_mode = $permalink_manager_options['miscellaneous']['redirect']; |
| 252 | |
| 253 | // Ignore default URIs (or do nothing if redirects are disabled) |
| 254 | if(!empty($active_permalink) && !empty($redirect_mode)) { |
| 255 | wp_redirect($active_permalink, $redirect_mode); |
| 256 | exit(); |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | function disable_canonical_redirect() { |
| 261 | global $permalink_manager_options; |
| 262 | if(!($permalink_manager_options['miscellaneous']['canonical_redirect'])) { |
| 263 | remove_action('template_redirect', 'redirect_canonical'); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | } |
| 268 | |
| 269 | /** |
| 270 | * Begins execution of the plugin. |
| 271 | */ |
| 272 | function run_permalink_manager() { |
| 273 | $Permalink_Manager_Class = new Permalink_Manager_Class(); |
| 274 | } |
| 275 | |
| 276 | run_permalink_manager(); |
| 277 |