PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 1.1.0
Permalink Manager Lite v1.1.0
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
424 lines
1 <?php
2
3 /**
4 * Plugin Name: Permalink Manager
5 * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
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.1.0
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
16 // If this file is called directly or plugin is already defined, abort.
17 if (!defined('WPINC')) {
18 die;
19 }
20
21 // Define the directories used to load plugin files.
22 define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23 define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24 define( 'PERMALINK_MANAGER_VERSION', '1.1.0' );
25 define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
26 define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
27 define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
28 define( 'PERMALINK_MANAGER_WEBSITE', 'http://permalinkmanager.pro?utm_source=plugin' );
29 define( 'PERMALINK_MANAGER_DONATE', 'https://www.paypal.me/Bismit' );
30
31 class Permalink_Manager_Class {
32
33 public $permalink_manager, $permalink_manager_options_page, $permalink_manager_options;
34 public $sections, $functions, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
35
36 /**
37 * Get options from DB, load subclasses & hooks
38 */
39 public function __construct() {
40 $this->include_subclassess();
41 $this->register_init_hooks();
42 }
43
44 /**
45 * Include back-end classess and set their instances
46 */
47 function include_subclassess() {
48 // WP_List_Table needed for post types & taxnomies editors
49 if( ! class_exists( 'WP_List_Table' ) ) {
50 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
51 }
52
53 $classes = array(
54 'core' => array(
55 'helper-functions' => 'Permalink_Manager_Helper_Functions',
56 'uri-functions-post' => 'Permalink_Manager_URI_Functions_Post',
57 'uri-functions-tax' => 'Permalink_Manager_URI_Functions_Tax',
58 'admin-functions' => 'Permalink_Manager_Admin_Functions',
59 'actions' => 'Permalink_Manager_Actions',
60 'third-parties' => 'Permalink_Manager_Third_Parties',
61 'pro-functions' => 'Permalink_Manager_Pro_Functions'
62 ),
63 'views' => array(
64 'uri-editor' => 'Permalink_Manager_Uri_Editor',
65 'tools' => 'Permalink_Manager_Tools',
66 'permastructs' => 'Permalink_Manager_Permastructs',
67 'settings' => 'Permalink_Manager_Settings',
68 'debug' => 'Permalink_Manager_Debug',
69 'pro-addons' => 'Permalink_Manager_Pro_Addons',
70 'uri-editor-tax' => false,
71 'uri-editor-post' => false
72 )
73 );
74
75 // Load classes and set-up their instances
76 foreach($classes as $class_type => $classes_array) {
77 foreach($classes_array as $class => $class_name) {
78 $filename = PERMALINK_MANAGER_DIR . "/includes/{$class_type}/permalink-manager-{$class}.php";
79
80 if(file_exists($filename)) {
81 require_once $filename;
82 if($class_name) { $this->functions[$class] = new $class_name(); }
83 }
84 }
85 }
86 }
87
88 /**
89 * Register general hooks
90 */
91 public function register_init_hooks() {
92 // Localize plugin
93 add_action( 'plugins_loaded', array($this, 'localize_me'), 1 );
94
95 // Load options
96 add_action( 'init', array($this, 'get_options_and_globals'), 1 );
97
98 // Use the URIs set in this plugin + redirect from old URIs to new URIs + adjust canonical redirect settings
99 add_action( 'wp', array($this, 'disable_canonical_redirect'), 0, 1 );
100 add_action( 'template_redirect', array($this, 'redirect_to_new_uri'), 999);
101 add_filter( 'request', array($this, 'detect_post'), 0, 1 );
102
103 // Legacy support
104 add_action( 'init', array($this, 'legacy_support'), 2 );
105
106 // Check for updates
107 // add_action( 'init', array($this, 'check_for_updates'), 999 );
108
109 // Default settings & alerts
110 add_filter( 'permalink-manager-options', array($this, 'default_settings'), 1 );
111 add_filter( 'permalink-manager-alerts', array($this, 'default_alerts'), 1 );
112 }
113
114 /**
115 * Localize this plugin
116 */
117 function localize_me() {
118 load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
119 }
120
121 /**
122 * Get options values & set global
123 */
124 public function get_options_and_globals() {
125 // 1. Globals with data stored in DB
126 global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs;
127
128 $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager', array()));
129 $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris', array()));
130 $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
131
132 // 2. Globals used to display additional content (eg. alerts)
133 global $permalink_manager_alerts, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
134
135 $this->permalink_manager_alerts = $permalink_manager_alerts = apply_filters('permalink-manager-alerts', get_option('permalink-manager-alerts', array()));
136 $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', '');
137 $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', '');
138 }
139
140 /**
141 * Set the initial/default settings (including "Screen Options")
142 */
143 public function default_settings($settings) {
144 $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
145 $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
146
147 $default_settings = apply_filters('permalink-manager-default-options', array(
148 'screen-options' => array(
149 'per_page' => 20,
150 'post_statuses' => array('publish')
151 ),
152 'general' => array(
153 'force_custom_slugs' => 0,
154 'auto_update_uris' => 0,
155 ),
156 'miscellaneous' => array(
157 'yoast_primary_term' => 1,
158 'redirect' => "302",
159 'canonical_redirect' => 1,
160 )
161 ));
162
163 // Apply the default settings (if empty values) in all settings sections
164 return $settings + $default_settings;
165 }
166
167 /**
168 * Set the initial/default admin notices
169 */
170 public function default_alerts($alerts) {
171 $default_alerts = apply_filters('permalink-manager-default-alerts', array(
172 // 'pro' => array('txt' => sprintf(__("Need to change the permalinks for categories, tags, custom taxonomies or WooCommerce?<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and enjoy the additional features!</strong>", "permalink-manager"), PERMALINK_MANAGER_WEBSITE), 'type' => 'notice-info', 'show' => 1)
173 ));
174
175 // Apply the default settings (if empty values) in all settings sections
176 return $alerts + $default_alerts;
177 }
178
179 /**
180 * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin
181 */
182 function detect_post($query) {
183 global $wpdb, $permalink_manager_uris, $wp_filter;
184
185 // Check if any custom URI is used
186 if(!(is_array($permalink_manager_uris))) return $query;
187
188 // Used in debug mode
189 $old_query = $query;
190
191 /**
192 * 1. Prepare URL and check if it is correct
193 */
194 $protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === true ? 'https://' : 'http://';
195 $request_url = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
196 $home_url = trim(rtrim(get_option('home'), '/'));
197 $home_url = ($protocol == 'https://') ? str_replace("http://", "https://", $home_url) : str_replace("https://", "http://", $home_url); // Adjust prefix (it should be the same in both request & home_url)
198
199 if (filter_var($request_url, FILTER_VALIDATE_URL)) {
200 /**
201 * 1. Process URL & find the URI
202 */
203 // Remove .html suffix and domain name from URL and query (URLs ended with .html will work as aliases)
204 $request_url = trim(str_replace($home_url, "", $request_url), "/");
205
206 // Remove querystrings from URI
207 $request_url = strtok($request_url, '?');
208
209 // Use default REGEX to detect post
210 preg_match("/^(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $regex_parts);
211 $uri_parts['lang'] = false;
212 $uri_parts['uri'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
213 $uri_parts['endpoint'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
214 $uri_parts['endpoint_value'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
215
216 // Allow to filter the results by third-parties
217 $uri_parts = apply_filters('permalink-manager-detect-uri', $uri_parts, $request_url);
218
219 // Stop the function if $uri_parts is empty
220 if(empty($uri_parts)) return $query;
221
222 // Get the URI parts from REGEX parts
223 $lang = $uri_parts['lang'];
224 $uri = $uri_parts['uri'];
225 $endpoint = $uri_parts['endpoint'];
226 $endpoint_value = $uri_parts['endpoint_value'];
227
228 // Trim slashes
229 $uri = trim($uri, "/");
230
231 // Ignore URLs with no URI grabbed
232 if(empty($uri)) return $query;
233
234 /**
235 * 2. Check if found URI matches any element from custom uris array
236 */
237 $item_id = array_search($uri, $permalink_manager_uris);
238
239 // Check again in case someone added .html suffix to particular post (with .html suffix)
240 $item_id = (empty($item_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $item_id;
241
242 // Check again in case someone used post/tax IDs instead of slugs
243 $deep_detect_enabled = apply_filters('permalink-manager-deep-uri-detect', false);
244 if($deep_detect_enabled && (empty($item_id)) && isset($old_query['page'])) {
245 $item_id = array_search("{$uri}/{$endpoint_value}", $permalink_manager_uris);
246 $endpoint_value = $endpoint = "";
247 }
248
249 // Clear the original query before it is filtered
250 $query = ($item_id) ? array() : $query;
251
252 /**
253 * 3A. Custom URI assigned to taxonomy
254 */
255 if(strpos($item_id, 'tax-') !== false) {
256 // Remove the "tax-" prefix
257 $item_id = preg_replace("/[^0-9]/", "", $item_id);
258
259 // Filter detected post ID
260 $item_id = apply_filters('permalink-manager-detected-term-id', $item_id, $uri_parts);
261
262 // Get the variables to filter wp_query and double-check if tax exists
263 $term = get_term($item_id);
264 if(empty($term->taxonomy)) { return $query; }
265
266 // Get some term data
267 $query_parameter = ($term->taxonomy == 'category') ? 'category_name' : $term->taxonomy;
268 $term_ancestors = get_ancestors($item_id, $term->taxonomy);
269 $final_uri = $term->slug;
270
271 // Fix for hierarchical CPT & pages
272 if(empty($term_ancestors)) {
273 foreach ($term_ancestors as $parent) {
274 $parent = get_term($parent, $term->taxonomy);
275 if(!empty($parent->slug)) {
276 $final_uri = $parent->slug . '/' . $final_uri;
277 }
278 }
279 }
280
281 // Alter query parameters
282 $query[$query_parameter] = $final_uri;
283 }
284 /**
285 * 3B. Custom URI assigned to post/page/cpt item
286 */
287 else if(isset($item_id) && is_numeric($item_id)) {
288 // Fix for revisions
289 $is_revision = wp_is_post_revision($item_id);
290 $item_id = ($is_revision) ? $is_revision : $item_id;
291
292 // Filter detected post ID
293 $item_id = apply_filters('permalink-manager-detected-post-id', $item_id, $uri_parts);
294
295 $post_to_load = get_post($item_id);
296 $final_uri = $post_to_load->post_name;
297 $post_type = $post_to_load->post_type;
298
299 // Fix for hierarchical CPT & pages
300 if(!(empty($post_to_load->ancestors))) {
301 foreach ($post_to_load->ancestors as $parent) {
302 $parent = get_post( $parent );
303 if($parent && $parent->post_name) {
304 $final_uri = $parent->post_name . '/' . $final_uri;
305 }
306 }
307 }
308
309 // Alter query parameters
310 if($post_to_load->post_type == 'page') {
311 $query['pagename'] = $final_uri;
312 } else if($post_to_load->post_type == 'post') {
313 $query['name'] = $final_uri;
314 } else {
315 $query['name'] = $final_uri;
316 $query['post_type'] = $post_type;
317 $query[$post_type] = $final_uri;
318 }
319
320 // Make the redirects more clever - see redirect_to_new_uri() method
321 $query['do_not_redirect'] = 1;
322 }
323
324 /**
325 * 2C. Endpoints
326 */
327 if($item_id && !(empty($endpoint_value))) {
328 $endpoint = ($endpoint) ? str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint) : "page";
329 $query[$endpoint] = $endpoint_value;
330 }
331
332 }
333
334 // Debug mode
335 if(isset($_REQUEST['debug_url'])) {
336 $debug_info['old_query_vars'] = $old_query;
337 $debug_info['new_query_vars'] = $query;
338
339 $debug_txt = json_encode($debug_info);
340 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
341 wp_die($debug_txt);
342 }
343
344 return $query;
345 }
346
347 function redirect_to_new_uri() {
348 global $wp, $wp_query, $permalink_manager_uris, $permalink_manager_options;
349
350 // Affect only posts with custom URI and old URIs
351 if(is_singular() && isset($permalink_manager_uris[$wp_query->queried_object_id]) && empty($wp_query->query['do_not_redirect']) && empty($wp_query->query['preview'])) {
352 // Ignore posts with specific statuses
353 if(!(empty($wp_query->queried_object->post_status)) && in_array($wp_query->queried_object->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
354 return '';
355 }
356
357 // Get the real URL
358 $correct_permalink = get_permalink($wp_query->queried_object_id);
359 }
360
361 // Get the redirection mode
362 $redirect_mode = $permalink_manager_options['miscellaneous']['redirect'];
363
364 // Ignore default URIs (or do nothing if redirects are disabled)
365 if(!empty($correct_permalink) && !empty($redirect_mode)) {
366 wp_safe_redirect($correct_permalink, $redirect_mode);
367 exit();
368 }
369 }
370
371 function disable_canonical_redirect() {
372 global $permalink_manager_options;
373 if(!($permalink_manager_options['miscellaneous']['canonical_redirect'])) {
374 remove_action('template_redirect', 'redirect_canonical');
375 }
376 }
377
378 /**
379 * Temporary hook
380 */
381 function legacy_support() {
382 global $permalink_manager_permastructs, $permalink_manager_options;
383
384 if(isset($permalink_manager_options['base-editor'])) {
385 $new_options['post_types'] = $permalink_manager_options['base-editor'];
386 update_option('permalink-manager-permastructs', $new_options);
387 }
388 else if(empty($permalink_manager_permastructs['post_types']) && count($permalink_manager_permastructs) > 0) {
389 $new_options['post_types'] = $permalink_manager_permastructs;
390 update_option('permalink-manager-permastructs', $new_options);
391 }
392 }
393
394 /**
395 * Update check
396 */
397 public function check_for_updates() {
398 global $permalink_manager_options;
399
400 // Load Plugin Update Checker by YahnisElsts
401 require_once PERMALINK_MANAGER_DIR . '/includes/ext/plugin-update-checker/plugin-update-checker.php';
402
403 // Get the licence key
404 $license_key = (!empty($permalink_manager_options['miscellaneous']['license_key'])) ? $permalink_manager_options['miscellaneous']['license_key'] : "";
405
406 $UpdateChecker = Puc_v4_Factory::buildUpdateChecker(
407 "https://updates.permalinkmanager.pro/?action=get_metadata&slug=permalink-manager-pro&license_key={$license_key}",
408 __FILE__,
409 "permalink-manager-pro"
410 );
411
412 $file = PERMALINK_MANAGER_BASENAME;
413 }
414
415 }
416
417 /**
418 * Begins execution of the plugin.
419 */
420 function run_permalink_manager() {
421 $Permalink_Manager_Class = new Permalink_Manager_Class();
422 }
423 run_permalink_manager();
424