PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 1.0.4
Permalink Manager Lite v1.0.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 / 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
354 lines
1 <?php
2
3 /**
4 * Plugin Name: Permalink Manager
5 * Plugin URI: https://permalinkmanager.pro
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.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', '1.0.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://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_option('home'), '/'));
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 // Remove querystrings from URI
157 $request_url = strtok($request_url, '?');
158
159 // Split the current URL into subparts (check if WPML is active)
160 if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
161 preg_match("/^(?:(\w{2})\/)?(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $url_parts);
162 $lang = (!empty($url_parts[1])) ? $url_parts[1] : "";
163 $uri = (!empty($url_parts[2])) ? $url_parts[2] : "";
164 $endpoint = (!empty($url_parts[3])) ? $url_parts[3] : "";
165 $endpoint_value = (!empty($url_parts[4])) ? $url_parts[4] : "";
166 } else {
167 preg_match("/^(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $url_parts);
168 $lang = false;
169 $uri = (!empty($url_parts[1])) ? $url_parts[1] : "";
170 $endpoint = (!empty($url_parts[2])) ? $url_parts[2] : "";
171 $endpoint_value = (!empty($url_parts[3])) ? $url_parts[3] : "";
172 }
173
174 // Trim slashes
175 $uri = trim($uri, "/");
176
177 // Ignore URLs with no URI grabbed
178 if(empty($uri)) return $query;
179
180 /**
181 * 2A. Check if found URI matches any element from custom uris array
182 */
183 $item_id = array_search($uri, $permalink_manager_uris);
184
185 // Check again in case someone added .html suffix to particular post (with .html suffix)
186 $item_id = (empty($item_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $item_id;
187
188 // Check again in case someone used post/tax IDs instead of slugs
189 $deep_detect_enabled = apply_filters('permalink_manager_deep_uri_detect', false);
190 if($deep_detect_enabled && (empty($item_id)) && isset($old_query['page'])) {
191 $item_id = array_search("{$uri}/{$endpoint_value}", $permalink_manager_uris);
192 $endpoint_value = $endpoint = "";
193 }
194
195 // Clear the original query before it is filtered
196 $query = ($item_id) ? array() : $query;
197
198 /**
199 * 2B. Custom URI assigned to taxonomy
200 */
201 if(strpos($item_id, 'tax-') !== false) {
202 // Remove the "tax-" prefix
203 $item_id = preg_replace("/[^0-9]/", "", $item_id);
204
205 // Get the variables to filter wp_query and double-check if tax exists
206 $term = get_term($item_id);
207 if(empty($term->taxonomy)) { return $query; }
208
209 // Get some term data
210 $query_parameter = ($term->taxonomy == 'category') ? 'category_name' : $term->taxonomy;
211 $term_ancestors = get_ancestors($item_id, $term->taxonomy);
212 $final_uri = $term->slug;
213
214 // Fix for hierarchical CPT & pages
215 if(empty($term_ancestors)) {
216 foreach ($term_ancestors as $parent) {
217 $parent = get_term($parent, $term->taxonomy);
218 if(!empty($parent->slug)) {
219 $final_uri = $parent->slug . '/' . $final_uri;
220 }
221 }
222 }
223
224 // Alter query parameters
225 $query[$query_parameter] = $final_uri;
226 }
227 /**
228 * 2C. Custom URI assigned to post/page/cpt item
229 */
230 else if(isset($item_id) && is_numeric($item_id)) {
231 // Fix for revisions
232 $is_revision = wp_is_post_revision($item_id);
233 $item_id = ($is_revision) ? $is_revision : $item_id;
234
235 // Fix for WPML languages mismatch
236 $post_lang_details = apply_filters('wpml_post_language_details', NULL, $item_id);
237 if(is_array($post_lang_details)) {
238 $language_code = (!empty($post_lang_details['language_code'])) ? $post_lang_details['language_code'] : '';
239 if($lang && ($lang != $language_code)) {
240 $wpml_item_id = apply_filters('wpml_object_id', $item_id);
241 $item_id = (is_numeric($wpml_item_id)) ? $wpml_item_id : $item_id;
242 }
243 }
244
245 $post_to_load = get_post($item_id);
246 $final_uri = $post_to_load->post_name;
247 $post_type = $post_to_load->post_type;
248
249 // Fix for hierarchical CPT & pages
250 if(!(empty($post_to_load->ancestors))) {
251 foreach ($post_to_load->ancestors as $parent) {
252 $parent = get_post( $parent );
253 if($parent && $parent->post_name) {
254 $final_uri = $parent->post_name . '/' . $final_uri;
255 }
256 }
257 }
258
259 // Alter query parameters
260 if($post_to_load->post_type == 'page') {
261 $query['pagename'] = $final_uri;
262 } else if($post_to_load->post_type == 'post') {
263 $query['name'] = $final_uri;
264 } else {
265 $query['name'] = $final_uri;
266 $query['post_type'] = $post_type;
267 $query[$post_type] = $final_uri;
268 }
269
270 // Make the redirects more clever - see redirect_to_new_uri() method
271 $query['do_not_redirect'] = 1;
272 }
273
274 /**
275 * 2C. Endpoints
276 */
277 if($item_id && !(empty($endpoint_value))) {
278 $endpoint = ($endpoint) ? str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint) : "page";
279 $query[$endpoint] = $endpoint_value;
280 }
281
282 }
283
284 // Debug mode
285 if(isset($_REQUEST['debug_url'])) {
286 $debug_info['old_query_vars'] = $old_query;
287 $debug_info['new_query_vars'] = $query;
288
289 $debug_txt = json_encode($debug_info);
290 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
291 wp_die($debug_txt);
292 }
293
294 return $query;
295 }
296
297 function redirect_to_new_uri() {
298 global $wp, $wp_query, $permalink_manager_uris, $permalink_manager_options;
299
300 // Affect only posts with custom URI and old URIs
301 if(is_singular() && isset($permalink_manager_uris[$wp_query->queried_object_id]) && empty($wp_query->query['do_not_redirect']) && empty($wp_query->query['preview'])) {
302 // Ignore posts with specific statuses
303 if(!(empty($wp_query->queried_object->post_status)) && in_array($wp_query->queried_object->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
304 return '';
305 }
306
307 // Get the real URL
308 $correct_permalink = get_permalink($wp_query->queried_object_id);
309 }
310
311 // Get the redirection mode
312 $redirect_mode = $permalink_manager_options['miscellaneous']['redirect'];
313
314 // Ignore default URIs (or do nothing if redirects are disabled)
315 if(!empty($correct_permalink) && !empty($redirect_mode)) {
316 wp_redirect($correct_permalink, $redirect_mode);
317 exit();
318 }
319 }
320
321 function disable_canonical_redirect() {
322 global $permalink_manager_options;
323 if(!($permalink_manager_options['miscellaneous']['canonical_redirect'])) {
324 remove_action('template_redirect', 'redirect_canonical');
325 }
326 }
327
328 /**
329 * Temporary hook
330 */
331 function legacy_support() {
332 global $permalink_manager_permastructs, $permalink_manager_options;
333
334 if(isset($permalink_manager_options['base-editor'])) {
335 $new_options['post_types'] = $permalink_manager_options['base-editor'];
336 update_option('permalink-manager-permastructs', $new_options);
337 }
338 else if(empty($permalink_manager_permastructs['post_types']) && count($permalink_manager_permastructs) > 0) {
339 $new_options['post_types'] = $permalink_manager_permastructs;
340 update_option('permalink-manager-permastructs', $new_options);
341 }
342 }
343
344 }
345
346 /**
347 * Begins execution of the plugin.
348 */
349 function run_permalink_manager() {
350 $Permalink_Manager_Class = new Permalink_Manager_Class();
351 }
352
353 run_permalink_manager();
354