PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 1.0.1
Permalink Manager Lite v1.0.1
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 / permalink-manager.php
permalink-manager Last commit date
includes 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
344 lines
1 <?php
2
3 /**
4 * Plugin Name: Permalink Manager
5 * Plugin URI: http://maciejbis.net/
6 * Description: Most advanced Permalink utility for Wordpress. It allows to bulk edit the permalinks & permastructures and regenerate/reset all the URIs in your Wordpress instance.
7 * Version: 1.0.1
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', '1.0.0' );
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://permalinkmanager.pro' );
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->register_init_hooks();
40 }
41
42 /**
43 * Include back-end classess and set their instances
44 */
45 function include_subclassess() {
46 // WP_List_Table needed for post types & taxnomies editors
47 if( ! class_exists( 'WP_List_Table' ) ) {
48 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
49 }
50
51 $classes = array(
52 'core' => array(
53 'helper-functions' => 'Permalink_Manager_Helper_Functions',
54 'uri-functions-post' => 'Permalink_Manager_URI_Functions_Post',
55 'uri-functions-tax' => 'Permalink_Manager_URI_Functions_Tax',
56 'admin-functions' => 'Permalink_Manager_Admin_Functions',
57 'actions' => 'Permalink_Manager_Actions',
58 'pro-hooks' => 'Permalink_Manager_Pro_Hooks'
59 ),
60 'views' => array(
61 'uri-editor' => 'Permalink_Manager_Uri_Editor',
62 'tools' => 'Permalink_Manager_Tools',
63 'permastructs' => 'Permalink_Manager_Permastructs',
64 'settings' => 'Permalink_Manager_Settings',
65 'advanced' => 'Permalink_Manager_Advanced',
66 'uri-editor-tax' => false,
67 'uri-editor-post' => false
68 )
69 );
70
71 // Load classes and set-up their instances
72 foreach($classes as $class_type => $classes_array) {
73 foreach($classes_array as $class => $class_name) {
74 $filename = PERMALINK_MANAGER_DIR . "/includes/{$class_type}/permalink-manager-{$class}.php";
75
76 if(file_exists($filename)) {
77 require_once $filename;
78 if($class_name) { $this->functions[$class] = new $class_name(); }
79 }
80 }
81 }
82 }
83
84 /**
85 * Register general hooks
86 */
87 public function register_init_hooks() {
88 // Localize plugin
89 add_action( 'plugins_loaded', array($this, 'localize_me'), 1 );
90
91 // Load options
92 add_action( 'init', array($this, 'get_options_and_globals'), 1 );
93
94 // Use the URIs set in this plugin + redirect from old URIs to new URIs + adjust canonical redirect settings
95 add_action( 'wp', array($this, 'disable_canonical_redirect'), 0, 1 );
96 add_action( 'template_redirect', array($this, 'redirect_to_new_uri'), 999);
97 add_filter( 'request', array($this, 'detect_post'), 0, 1 );
98
99 // Legacy support
100 add_action( 'init', array($this, 'legacy_support'), 2 );
101 }
102
103 /**
104 * Localize this plugin
105 */
106 function localize_me() {
107 load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
108 }
109
110 /**
111 * Get options values & set global
112 */
113 public function get_options_and_globals() {
114 // 1. Globals with data stored in DB
115 global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs;
116
117 $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager', array()));
118 $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris', array()));
119 $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
120
121 // 2. Globals used to display additional content (eg. alerts)
122 global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
123
124 $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', '');
125 $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', '');
126 }
127
128 /**
129 * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin
130 */
131 function detect_post($query) {
132 global $wpdb, $permalink_manager_uris, $sitepress_settings;
133
134 // Check if any custom URI is used
135 if(!(is_array($permalink_manager_uris))) return $query;
136
137 // Used in debug mode
138 $old_query = $query;
139
140 /**
141 * 1. Prepare URL and check if it is correct
142 */
143 $protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === true ? 'https://' : 'http://';
144 $request_url = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
145 $home_url = trim(rtrim(get_bloginfo('url'), '/'));
146 // Adjust prefix (it should be the same in both request & home_url)
147 $home_url = ($protocol == 'https://') ? str_replace("http://", "https://", $home_url) : str_replace("https://", "http://", $home_url);
148
149 if (filter_var($request_url, FILTER_VALIDATE_URL)) {
150 /**
151 * 2. Process URL
152 */
153 // Remove .html suffix and domain name from URL and query (URLs ended with .html will work as aliases)
154 $request_url = trim(str_replace($home_url, "", $request_url), "/");
155
156 // Split the current URL into subparts (check if WPML is active)
157 if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
158 preg_match("/^(?:(\w{2})\/)?(.+)\/?(?:(page|feed|embed|attachment|track)\/([\d+])?)?$/i", $request_url, $url_parts);
159 $lang = (!empty($url_parts[1])) ? $url_parts[1] : "";
160 $uri = (!empty($url_parts[2])) ? $url_parts[2] : "";
161 $endpoint = (!empty($url_parts[3])) ? $url_parts[3] : "";
162 $endpoint_value = (!empty($url_parts[4])) ? $url_parts[4] : "";
163 } else {
164 preg_match("/^(.+)\/?(?:(page|feed|embed|attachment|track)\/([\d+])?)?$/i", $request_url, $url_parts);
165 $lang = false;
166 $uri = (!empty($url_parts[1])) ? $url_parts[1] : "";
167 $endpoint = (!empty($url_parts[2])) ? $url_parts[2] : "";
168 $endpoint_value = (!empty($url_parts[3])) ? $url_parts[3] : "";
169 }
170
171 // Ignore URLs with no URI grabbed
172 if(empty($uri)) return $query;
173
174 // Remove querystrings from URI
175 $uri = trim(strtok($uri, '?'), "/");
176
177 /**
178 * 2A. Check if found URI matches any element from custom uris array
179 */
180 $item_id = array_search($uri, $permalink_manager_uris);
181
182 // Check again in case someone added .html suffix to particular post (with .html suffix)
183 $item_id = (empty($item_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $item_id;
184
185 // Clear the original query before it is filtered
186 $query = ($item_id) ? array() : $query;
187
188 /**
189 * 2B. Custom URI assigned to taxonomy
190 */
191 if(strpos($item_id, 'tax-') !== false) {
192 // Remove the "tax-" prefix
193 $item_id = preg_replace("/[^0-9]/", "", $item_id);
194
195 // Get the variables to filter wp_query and double-check if tax exists
196 $term = get_term($item_id);
197 if(empty($term->taxonomy)) { return $query; }
198
199 // Get some term data
200 $query_parameter = ($term->taxonomy == 'category') ? 'category_name' : $term->taxonomy;
201 $term_ancestors = get_ancestors($item_id, $term->taxonomy);
202 $final_uri = $term->slug;
203
204 // Fix for hierarchical CPT & pages
205 if(empty($term_ancestors)) {
206 foreach ($term_ancestors as $parent) {
207 $parent = get_term($parent, $term->taxonomy);
208 if(!empty($parent->slug)) {
209 $final_uri = $parent->slug . '/' . $final_uri;
210 }
211 }
212 }
213
214 // Alter query parameters
215 $query[$query_parameter] = $final_uri;
216 }
217 /**
218 * 2C. Custom URI assigned to post/page/cpt item
219 */
220 else if(isset($item_id) && is_numeric($item_id)) {
221 // Fix for revisions
222 $is_revision = wp_is_post_revision($item_id);
223 $item_id = ($is_revision) ? $is_revision : $item_id;
224
225 // Fix for WPML languages mismatch
226 $post_lang_details = apply_filters('wpml_post_language_details', NULL, $item_id);
227 $language_code = (!empty($post_lang_details['language_code'])) ? $post_lang_details['language_code'] : '';
228 if($lang && $lang != $language_code) {
229 $item_id = apply_filters('wpml_object_id', $item_id);
230 }
231
232 $post_to_load = get_post($item_id);
233 $final_uri = $post_to_load->post_name;
234 $post_type = $post_to_load->post_type;
235
236 // Fix for hierarchical CPT & pages
237 if(!(empty($post_to_load->ancestors))) {
238 foreach ($post_to_load->ancestors as $parent) {
239 $parent = get_post( $parent );
240 if($parent && $parent->post_name) {
241 $final_uri = $parent->post_name . '/' . $final_uri;
242 }
243 }
244 }
245
246 // Alter query parameters
247 if($post_to_load->post_type == 'page') {
248 $query['pagename'] = $final_uri;
249 } else if($post_to_load->post_type == 'post') {
250 $query['name'] = $final_uri;
251 } else {
252 $query['name'] = $final_uri;
253 $query['post_type'] = $post_type;
254 $query[$post_type] = $final_uri;
255 }
256
257 // Make the redirects more clever - see redirect_to_new_uri() method
258 $query['do_not_redirect'] = 1;
259 }
260
261 /**
262 * 2C. Endpoints
263 */
264 if(!(empty($endpoint_value))) {
265 $endpoint = str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint);
266 $query[$endpoint] = $endpoint_value;
267 }
268
269 }
270
271 // Debug mode
272 if(isset($_REQUEST['debug_url'])) {
273 $debug_info['old_query_vars'] = $old_query;
274 $debug_info['new_query_vars'] = $query;
275
276 $debug_txt = json_encode($debug_info);
277 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
278 wp_die($debug_txt);
279 }
280
281 return $query;
282 }
283
284 function redirect_to_new_uri() {
285 global $wp, $wp_query, $permalink_manager_uris, $permalink_manager_options;
286
287 // Affect only posts with custom URI and old URIs
288 if(is_singular() && isset($permalink_manager_uris[$wp_query->queried_object_id]) && empty($wp_query->query['do_not_redirect']) && empty($wp_query->query['preview'])) {
289 // Ignore posts with specific statuses
290 if(!(empty($wp_query->queried_object->post_status)) && in_array($wp_query->queried_object->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
291 return '';
292 }
293
294 // Get the real URL
295 $current_url = home_url(add_query_arg(array(),$wp->request));
296 $native_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($permalink_manager_uris[$wp_query->queried_object_id], true);
297
298 $active_permalink = str_replace($native_uri, $permalink_manager_uris[$wp_query->queried_object_id], $current_url);
299 }
300
301 // Get the redirection mode
302 $redirect_mode = $permalink_manager_options['miscellaneous']['redirect'];
303
304 // Ignore default URIs (or do nothing if redirects are disabled)
305 if(!empty($active_permalink) && !empty($redirect_mode)) {
306 wp_redirect($active_permalink, $redirect_mode);
307 exit();
308 }
309 }
310
311 function disable_canonical_redirect() {
312 global $permalink_manager_options;
313 if(!($permalink_manager_options['miscellaneous']['canonical_redirect'])) {
314 remove_action('template_redirect', 'redirect_canonical');
315 }
316 }
317
318 /**
319 * Temporary hook
320 */
321 function legacy_support() {
322 global $permalink_manager_permastructs, $permalink_manager_options;
323
324 if(isset($permalink_manager_options['base-editor'])) {
325 $new_options['post_types'] = $permalink_manager_options['base-editor'];
326 update_option('permalink-manager-permastructs', $new_options);
327 }
328 else if(empty($permalink_manager_permastructs['post_types']) && count($permalink_manager_permastructs) > 0) {
329 $new_options['post_types'] = $permalink_manager_permastructs;
330 update_option('permalink-manager-permastructs', $new_options);
331 }
332 }
333
334 }
335
336 /**
337 * Begins execution of the plugin.
338 */
339 function run_permalink_manager() {
340 $Permalink_Manager_Class = new Permalink_Manager_Class();
341 }
342
343 run_permalink_manager();
344