PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 0.4.9
Permalink Manager Lite v0.4.9
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
css 9 years ago inc 9 years ago js 9 years ago languages 9 years ago LICENSE.txt 9 years ago README.txt 9 years ago permalink-manager.php 9 years ago
permalink-manager.php
788 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.4.9
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, 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_VERSION', '0.4.9' );
24 define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
25 define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
26 define( 'PERMALINK_MANAGER_WEBSITE', 'http://maciejbis.net' );
27 define( 'PERMALINK_MANAGER_MENU_PAGE', 'tools_page_permalink-manager' );
28 define( 'PERMALINK_MANAGER_OPTIONS_PAGE', PERMALINK_MANAGER_PLUGIN_NAME . '.php' );
29
30 class Permalink_Manager_Class {
31
32 protected $permalink_manager, $admin_page, $permalink_manager_options_page, $permalink_manager_options;
33
34 public function __construct() {
35
36 $this->permalink_manager_options = get_option('permalink-manager');
37 $this->permalink_manager_uris = get_option('permalink-manager-uris');
38 $this->permalink_manager_permastructs = get_option('permalink-manager-permastructs');
39
40 if( is_admin() ) {
41 add_action( 'plugins_loaded', array($this, 'localize_me') );
42 add_action( 'init', array($this, 'upgrade_plugin'), 999 );
43 add_action( 'init', array($this, 'debug_functions'), 999999999999 );
44 add_action( 'wp_loaded', array($this, 'bulk_actions'), 1 );
45 add_action( 'admin_menu', array($this, 'add_menu_page') );
46 add_action( 'save_post', array($this, 'update_single_uri'), 10, 3 );
47 add_action( 'wp_trash_post', array($this, 'remove_single_uri'), 10, 3 );
48 add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugins_page_links') );
49 add_filter( 'get_sample_permalink_html', array($this, 'edit_uri_box'), 10, 4 );
50 }
51
52 add_action( 'wp_loaded', array($this, 'permalink_filters'), 999);
53 add_action( 'template_redirect', array($this, 'redirect_to_new_uri'), 999);
54
55 }
56
57 function permalink_filters() {
58 // Public functions
59 add_filter( 'request', array($this, 'detect_post'), 0, 1 );
60 add_filter( '_get_page_link', array($this, 'custom_permalinks'), 999, 2);
61 add_filter( 'page_link', array($this, 'custom_permalinks'), 999, 2);
62 add_filter( 'post_link', array($this, 'custom_permalinks'), 999, 2);
63 add_filter( 'post_type_link', array($this, 'custom_permalinks'), 999, 2);
64 }
65
66 /**
67 * Localize this plugin
68 */
69 function localize_me() {
70 load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
71 }
72
73 /**
74 * Add menu page and load CSS & JS.
75 */
76 function add_menu_page() {
77 add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', PERMALINK_MANAGER_OPTIONS_PAGE, array($this, 'list_slugs_admin_page') );
78
79 // Make sure thata the CSS and JS files are loaded only on plugin admin page.
80 add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_styles' ) );
81 add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_scripts' ) );
82 }
83
84 /**
85 * Display the table with slugs.
86 */
87 function slug_editor_html() {
88 global $wpdb;
89
90 $Permalink_Manager_Editor = new Permalink_Manager_Editor();
91 $Permalink_Manager_Editor->set_screen_option_fields($this->fields_arrays('screen_options'));
92 $Permalink_Manager_Editor->prepare_items($wpdb->posts);
93
94 ?>
95
96 <form id="permalinks-table" method="post">
97 <input type="hidden" name="tab" value="slug_editor" />
98 <?php echo $Permalink_Manager_Editor->display(); ?>
99 </form>
100 <?php
101 }
102
103 /**
104 * Mass replace options page.
105 */
106 function find_and_replace_html() {
107 $button = get_submit_button( __( 'Find & Replace Slugs', 'permalink-manager' ), 'primary', 'find-replace-button', false );
108
109 $return = "<form id=\"permalinks-table-find-replace\" method=\"post\">";
110 $return .= "<input type=\"hidden\" name=\"tab\" value=\"find_and_replace\" />";
111 $return .= "<table class=\"form-table\">";
112
113 foreach($this->fields_arrays('find_and_replace') as $field_name => $field_args) {
114 $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'find-replace');
115 }
116
117 $return .= "</table>{$button}";
118 $return .= "</form>";
119
120 echo $return;
121 }
122
123 /**
124 * Reset slugs page.
125 */
126 function regenerate_slugs_html() {
127 $button = get_submit_button( __( 'Regenerate', 'permalink-manager' ), 'primary', 'regenerate-button', false );
128
129 $return = "<form id=\"permalinks-table-regenerate\" method=\"post\">";
130 $return .= "<input type=\"hidden\" name=\"tab\" value=\"regenerate_slugs\" />";
131 $return .= "<table class=\"form-table\">";
132
133 foreach($this->fields_arrays('regenerate_slugs') as $field_name => $field_args) {
134 $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'regenerate_slugs');
135 }
136
137 $return .= "</table>{$button}";
138 $return .= "</form>";
139
140 echo $return;
141 }
142
143 /**
144 * Permalink Base Editor
145 */
146 function base_editor_html() {
147 global $wpdb, $wp_rewrite;
148
149 $Permalink_Manager_Base_Editor = new Permalink_Manager_Base_Editor();
150 $Permalink_Manager_Base_Editor->set_screen_option_fields($this->fields_arrays('screen_options'));
151 $Permalink_Manager_Base_Editor->prepare_items($wpdb->posts);
152 ?>
153
154 <form id="permalinks-base-table" method="post">
155 <input type="hidden" name="tab" value="base_editor" />
156 <?php echo $Permalink_Manager_Base_Editor->display(); ?>
157 </form>
158 <?php
159 }
160
161 /**
162 * Display the plugin dashboard.
163 */
164 function list_slugs_admin_page() {
165 global $wpdb;
166
167 // Check which tab is active now.
168 if(isset($_POST['tab'])) {
169 $active_tab = $_POST['tab'];
170 } else if(isset($_GET['tab'])) {
171 $active_tab = $_GET['tab'];
172 } else {
173 $active_tab = 'slug_editor';
174 }
175
176 // Tabs array with assigned functions used to display HTML content.
177 $tabs = array(
178 'slug_editor' => array(
179 'name' => __('Permalink editor', 'permalink-manager'),
180 'function' => 'slug_editor_html',
181 'description' => __('You can disable/enable selected post types from the table below using <strong>"Screen Options"</strong> (click on the upper-right button to show it) section above.', 'permalink-manager'),
182 ),
183 'find_and_replace' => array(
184 'name' => __('Find and replace', 'permalink-manager'),
185 'function' => 'find_and_replace_html'
186 ),
187 'regenerate_slugs' => array(
188 'name' => __('Regenerate/Reset', 'permalink-manager'),
189 'function' => 'regenerate_slugs_html'
190 ),
191 'base_editor' => array(
192 'name' => __('Base editor', 'permalink-manager'),
193 'function' => 'base_editor_html',
194 'warning' => array(
195 sprintf(__('<strong>This is an experimental feature!</strong> Please report all the bugs & issues <a href="%s">here</a>.', 'permalink-manager'), 'https://wordpress.org/support/plugin/permalink-manager'),
196 __('Each Custom Post Type should have their own, unique front (eg. <em>products</em> for Products)', 'permalink-manager'),
197 __('Please note that the following settings will be applied only to new posts.<br />If you want to apply them to exisiting posts, you will need to regenerate the URIs in <strong>"Regnerate/Reset"</strong> section (with <strong>"Slugs & bases"</strong> option selected).', 'permalink-manager'),
198 ),
199 'description' => (sprintf( __('All the <a href="%s" target="_blank">Structure Tags</a> allowed are listed below. Please note that some of them can be used only for particular Post Types.', 'permalink-manager'), "https://codex.wordpress.org/Using_Permalinks#Structure_Tags") . "<br />" . Permalink_Manager_Helper_Functions::get_all_structure_tags())
200 ),
201 );
202
203 ?>
204 <div id="permalinks-table-wrap" class="wrap">
205
206 <?php
207 // Display alerts and another content if needed
208 echo apply_filters('permalink-manager-before-tabs','');
209 ?>
210
211 <div id="icon-themes" class="icon32"></div>
212 <h2 id="plugin-name-heading"><?php _e('Permalink Manager', 'permalink-manager'); ?> <a href="<?php echo PERMALINK_MANAGER_WEBSITE; ?>" target="_blank"><?php _e('by Maciej Bis', 'permalink-manager'); ?></a></h2>
213
214 <h2 id="permalink-manager-tabs-nav" class="nav-tab-wrapper">
215 <?php
216 foreach($tabs as $tab_id => $tab_properties) {
217 $active_class = ($active_tab === $tab_id) ? 'nav-tab-active nav-tab' : 'nav-tab';
218 echo '<a data-tab="' . $tab_id . '" href="' . admin_url('admin.php?page=' . PERMALINK_MANAGER_PLUGIN_NAME . '.php&tab=' . $tab_id) . '" class="' . $active_class . '">' . $tab_properties['name'] . '</a>';
219 } ?>
220 </h2>
221
222 <div id="permalink-manager-tabs">
223 <?php
224 foreach($tabs as $tab_id => $tab_properties) {
225 $active_show = ($active_tab === $tab_id) ? 'show' : '';
226
227 // Prepare warning & description texts
228 $warning = (isset($tab_properties['warning'])) ? $tab_properties['warning'] : '';
229 $description = (isset($tab_properties['description'])) ? $tab_properties['description'] : '';
230
231 if(is_array($warning)) {
232 $warning = "<ol>"; // Overwrite the variable
233 foreach($tab_properties['warning'] as $point) { $warning .= "<li>{$point}</li>"; }
234 $warning .= "</ol>";
235 }
236
237 if(is_array($description)) {
238 $description = "<ol>"; // Overwrite the variable
239 foreach($tab_properties['description'] as $point) { $description .= "<li>{$point}</li>"; }
240 $description .= "</ol>";
241 }
242
243 echo '<div data-tab="' . $tab_id . '" id="' . $tab_id . '" class="' . $active_show . '">';
244 echo ($warning) ? "<div class=\"warning alert\">" . wpautop($warning) . "</div>" : "";
245 echo (isset($tab_properties['description'])) ? "<div class=\"info alert\">" . wpautop($description) . "</div>" : "";
246 $function_name = $tab_properties['function'];
247 $this->$function_name();
248 echo '</div>';
249 } ?>
250 </div>
251
252 <?php
253 // Display alerts and another content if needed
254 echo apply_filters('permalink-manager-after-tabs','');
255 ?>
256
257 </div>
258 <?php
259 }
260
261 /**
262 * Register the stylesheets for the Dashboard.
263 */
264 function enqueue_styles() {
265 wp_enqueue_style( PERMALINK_MANAGER_PLUGIN_NAME, PERMALINK_MANAGER_URL . '/css/permalink-manager-admin.css', array(), PERMALINK_MANAGER_VERSION, 'all' );
266 }
267
268 /**
269 * Register the JavaScript for the dashboard.
270 */
271 function enqueue_scripts() {
272 wp_enqueue_script( PERMALINK_MANAGER_PLUGIN_NAME, PERMALINK_MANAGER_URL . '/js/permalink-manager-admin.js', array( 'jquery' ), PERMALINK_MANAGER_VERSION, false );
273 }
274
275 /**
276 * Additional links on "Plugins" page
277 */
278 function plugins_page_links( $links ) {
279 $links[] = '<a href="' . esc_url( get_admin_url(null, "tools.php?page=" . PERMALINK_MANAGER_OPTIONS_PAGE) ) .'">' . __( 'Go To Permalink Manager', 'permalink-manager' ) . '</a>';
280 return $links;
281 }
282
283 /**
284 * Fields for "Screen Options"
285 */
286 function fields_arrays($array) {
287
288 // All registered post types array
289 $all_post_statuses_array = get_post_statuses();
290 $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
291
292 // Fields for "Screen Options"
293 $screen_options = array(
294 'post_types' => array(
295 'label' => __( 'Post Types', 'permalink-manager' ),
296 'type' => 'checkbox',
297 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
298 'default' => array('post', 'page')
299 ),
300 'post_statuses' => array(
301 'label' => __( 'Post Statuses', 'permalink-manager' ),
302 'type' => 'checkbox',
303 'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
304 'default' => array('publish')
305 ),
306 'per_page' => array(
307 'label' => __( 'Per page', 'permalink-manager' ),
308 'type' => 'number',
309 'default' => 10
310 )
311 );
312
313 // Fields for "Find and replace"
314 $find_and_replace = array(
315 'clearfix1' => array(
316 'type' => 'clearfix'
317 ),
318 'old_string' => array(
319 'label' => __( 'Find ...', 'permalink-manager' ),
320 'type' => 'text',
321 'container_class' => 'half'
322 ),
323 'new_string' => array(
324 'label' => __( 'Replace with ...', 'permalink-manager' ),
325 'type' => 'text',
326 'container_class' => 'half half2'
327 ),
328 'clearfix2' => array(
329 'type' => 'clearfix'
330 ),
331 'variant' => array(
332 'label' => __( 'Select which elements should be affected', 'permalink-manager' ),
333 'type' => 'radio',
334 'choices' => array('both' => '<strong>' . __('Plugin Slugs & Bases (Full URIs)', 'permalink-manager') . '</strong>', 'slugs' => '<strong>' . __('Only Plugin Slugs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Plugin Slugs & Wordpress Native Slugs (Post Names)', 'permalink-manager') . '</strong>'),
335 'default' => array('slugs'),
336 'desc' => __('First two options will affect settings used only by this plugin.<br />A MySQL backup is recommended before using third option - it overwrites the value of <strong>post_name</strong> field (part of <strong>$post</strong> object used by Wordpress core).', 'permalink-manager')
337 ),
338 'post_types' => array(
339 'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
340 'type' => 'checkbox',
341 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
342 'default' => array('post', 'page')
343 ),
344 'post_statuses' => array(
345 'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
346 'type' => 'checkbox',
347 'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
348 'default' => array('publish')
349 )
350 );
351
352 // Fields for "Regenerate slugs"
353 $regenerate_slugs = array(
354 'variant' => array(
355 'label' => __( 'Select which elements should be affected', 'permalink-manager' ),
356 'type' => 'radio',
357 'choices' => array('both' => '<strong>' . __('Plugin Slugs & Bases (Full URIs)', 'permalink-manager') . '</strong>', 'slugs' => '<strong>' . __('Only Plugin Slugs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Plugin Slugs & Wordpress Native Slugs (Post Names)', 'permalink-manager') . '</strong>'),
358 'default' => array('slugs'),
359 'desc' => __('First two options will affect settings used only by this plugin.<br />A MySQL backup is recommended before using third option - it overwrites the value of <strong>post_name</strong> field (part of <strong>$post</strong> object used by Wordpress core).', 'permalink-manager')
360 ),
361 'post_types' => array(
362 'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
363 'type' => 'checkbox',
364 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
365 'default' => array('post', 'page')
366 ),
367 'post_statuses' => array(
368 'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
369 'type' => 'checkbox',
370 'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
371 'default' => array('publish')
372 )
373 );
374
375 return isset($array) ? ${$array} : array();
376
377 }
378
379 /**
380 * Bulk actions functions
381 */
382 function bulk_actions() {
383 global $wpdb;
384
385 // Trigger a selected function
386 if (isset($_POST['update_all_slugs'])) {
387 $output = Permalink_Manager_Actions::update_all_permalinks();
388 } else if (isset($_POST['find-replace-button'])) {
389 $output = Permalink_Manager_Actions::find_replace($this->fields_arrays('find_and_replace'));
390 } else if (isset($_POST['regenerate-button'])) {
391 $output = Permalink_Manager_Actions::regenerate_all_permalinks();
392 // Save Permalink Structures/Permalinks Bases
393 } else if (isset($_POST['save_permastructs'])) {
394 $output = Permalink_Manager_Actions::update_permastructs();
395 }
396
397 // Load variables
398 $updated_array = isset($output['updated']) ? $output['updated'] : array();
399 $updated_slugs_count = isset($output['updated_count']) ? $output['updated_count'] : 0;
400 $alert_content = isset($output['alert_content']) ? $output['alert_content'] : "";
401 $alert_type = isset($output['alert_type']) ? $output['alert_type'] : "";
402
403 /**
404 * Display results
405 */
406 if((isset($_POST['permalink-manager']) || isset($_POST['update_all_slugs'])) && !(isset($_POST['screen-options-apply']))) {
407 // Display errors or success message
408
409 // Check how many rows/slugs were affected
410 if (isset($_POST['save_permastructs'])) {
411 $alert_type = 'updated';
412 $alert_content = __( 'Permastructures were updated!', 'permalink-manager' ) . ' ';
413 } else if($updated_slugs_count > 0) {
414 $alert_type = 'updated';
415 $alert_content = sprintf( _n( '<strong>%d</strong> slug were updated!', '<strong>%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
416 $alert_content .= sprintf( __( '<a href="%s">Click here</a> to go to the list of updated slugs', 'permalink-manager' ), '#updated-list');
417 } else {
418 $alert_type = 'error';
419 $alert_content = ($alert_content) ? $alert_content : __( '<strong>No slugs</strong> were updated!', 'permalink-manager' );
420 }
421
422 Permalink_Manager_Helper_Functions::display_alert($alert_content, $alert_type, true);
423
424 // Display summary after update
425 // Display only if there are any slugs updated
426 if ( $updated_slugs_count > 0 && is_array($updated_array) ) {
427 add_filter('permalink-manager-after-tabs', function( $arg ) use ( $alert_content, $alert_type, $updated_array ) {
428
429 // Check if slugs should be displayed
430 $first_slug = reset($updated_array);
431
432 $header_footer = '<tr>';
433 $header_footer .= '<th class="column-primary">' . __('Title', 'permalink-manager') . '</th>';
434 $header_footer .= '<th>' . __('Old URI', 'permalink-manager') . '</th>';
435 $header_footer .= '<th>' . __('New URI', 'permalink-manager') . '</th>';
436 $header_footer .= (isset($first_slug['old_slug'])) ? '<th>' . __('Old Slug', 'permalink-manager') . '</th>' : "";
437 $header_footer .= (isset($first_slug['new_slug'])) ? '<th>' . __('New Slug', 'permalink-manager') . '</th>' : "";
438 $header_footer .= '</tr>';
439
440 $updated_slugs_count = 0;
441 $main_content = "";
442 foreach($updated_array as $row) {
443 // Odd/even class
444 $updated_slugs_count++;
445 $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
446 //$permalink = Permalink_Manager_Helper_Functions::get_correct_permalink($row[ 'ID' ]);
447 $permalink = home_url("{$row['new_uri']}");
448
449 $main_content .= "<tr{$alternate_class}>";
450 $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['post_title'] . "<a target=\"_blank\" href=\"{$permalink}\"><small>{$permalink}</small></a>" . '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __('Show more details', 'permalink-manager') . '</span></button></td>';
451 $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . $row['old_uri'] . '</td>';
452 $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . $row['new_uri'] . '</td>';
453 $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . $row['old_slug'] . '</td>' : "";
454 $main_content .= (isset($row['new_slug'])) ? '<td data-colname="' . __('New Slug', 'permalink-manager') . '">' . $row['new_slug'] . '</td>' : "";
455 $main_content .= '</tr>';
456 }
457
458 // Merge header, footer and content
459 $output = '<h3 id="updated-list">' . __('List of updated posts', 'permalink-manager') . '</h3>';
460 $output .= '<table class="widefat wp-list-table">';
461 $output .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
462 $output .= '</table>';
463
464 return $output ;
465
466 });
467 }
468 }
469 }
470
471 /**
472 * Change permalinks for posts, pages & custom post types
473 */
474 function custom_permalinks($permalink, $post) {
475 global $wp_rewrite, $permalink_manager;
476
477 $post = (is_integer($post)) ? get_post($post) : $post;
478 $post_type = $post->post_type;
479
480 // Do not change permalink of frontpage
481 if(get_option('page_on_front') == $post->ID) { return $permalink; }
482
483 $uris = $this->permalink_manager_uris;
484 if(isset($uris[$post->ID])) $permalink = home_url('/') . $uris[$post->ID];
485
486 return $permalink;
487 }
488
489 /**
490 * Used to optimize SQL queries amount instead of rewrite rules
491 */
492 function detect_post($query) {
493
494 global $wpdb;
495
496 // Used in debug mode
497 $old_query = $query;
498
499 // Get URL
500 $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
501 // Fix for Wordpress installed in subdirectories
502 $url = str_replace(home_url(), "{$protocol}{$_SERVER['HTTP_HOST']}", "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
503
504 // Remove .html suffix from URL and query (URLs ended with .html work as aliases)
505 $url = str_replace(".html", "", $url);
506 if(isset($query['name'])) { $query['name'] = str_replace('.html', '', $query['name']); }
507 if(isset($query['pagename'])) { $query['pagename'] = str_replace('.html', '', $query['pagename']); }
508
509 // Check if it is correct URL
510 if (filter_var($url, FILTER_VALIDATE_URL)) {
511
512 // Separate endpoints (if set) - support for comment pages will be added later
513 preg_match("/(.*)\/(page|feed|embed|attachment|track)\/(.*)/", $url, $url_with_endpoints);
514 if(isset($url_with_endpoints[3]) && !(empty($url_with_endpoints[3]))) {
515 $url = $url_with_endpoints[1];
516 $endpoint = str_replace(array('page', 'trackback'), array('paged', 'tb'), $url_with_endpoints[2]);
517 $endpoint_value = $url_with_endpoints[3];
518 }
519
520 // Parse URL
521 $url_parts = parse_url($url);
522 $uri = (isset($url_parts['path'])) ? trim($url_parts['path'], "/") : "";
523 if(empty($uri)) return $query;
524
525 // Check if current URL is assigned to any post
526 $uris = $this->permalink_manager_uris;
527 if(!(is_array($uris))) return $query;
528 $post_id = array_search($uri, $uris);
529
530 // Check again in case someone added .html suffix to particular post (with .html suffix)
531 $post_id = (empty($post_id)) ? array_search("{$uri}.html", $uris) : $post_id;
532
533 if(isset($post_id) && is_numeric($post_id)) {
534 // Check if it is revision (hotfix) and use original post ID instead of revision ID
535 $is_revision = wp_is_post_revision($post_id);
536 $post_id = ($is_revision) ? $is_revision : $post_id;
537
538 $post_to_load = get_post($post_id);
539 $original_page_uri = $post_to_load->post_name;
540 $post_type = $post_to_load->post_type;
541 unset($query['attachment']);
542 unset($query['error']);
543
544 // Fix for hierarchical CPT & pages
545 if( isset($post_to_load->ancestors) && !(empty($post_to_load->ancestors))) {
546 foreach ( $post_to_load->ancestors as $parent ) {
547 $parent = get_post( $parent );
548 if ( $parent && $parent->post_name ) {
549 $original_page_uri = $parent->post_name . '/' . $original_page_uri;
550 }
551 }
552 }
553
554 // Fix for not-pages
555 if($post_to_load->post_type != 'post') {
556 unset($query['year']);
557 unset($query['monthnum']);
558 unset($query['day']);
559 }
560
561 // Alter query parameters
562 if($post_to_load->post_type == 'page') {
563 unset($query['name']);
564 $query['pagename'] = $original_page_uri;
565 } else if($post_to_load->post_type == 'post') {
566 $query['name'] = $original_page_uri;
567 } else {
568 $query['name'] = $original_page_uri;
569 $query['post_type'] = $post_type;
570 $query[$post_type] = $original_page_uri;
571 }
572
573 // Add endpoint
574 if(isset($endpoint_value) && !(empty($endpoint_value))) {
575 $query[$endpoint] = $endpoint_value;
576 }
577 }
578
579 }
580
581 // Debug mode
582 if(isset($_REQUEST['debug_url'])) {
583 $debug_info['old_query_vars'] = $old_query;
584 $debug_info['new_query_vars'] = $query;
585 //$debug_info['request'] = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
586 $debug_info['request'] = $url;
587
588 $debug_txt = json_encode($debug_info);
589 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
590 wp_die($debug_txt);
591 }
592
593 return $query;
594 }
595
596 function redirect_to_new_uri() {
597 global $wp;
598
599 $uris = $this->permalink_manager_uris;
600 $object_id = get_queried_object_id();
601 $uri = isset($uris[$object_id]) ? home_url('/') . $uris[$object_id] : "";
602
603 $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
604 $request_uri = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER["REQUEST_URI"];
605
606 // Get the option value (will be added in 0.5 with additional option panel)
607 $redirects_activated = 1;
608
609 // Ignore default URIs
610 if(!($uri)) return;
611
612 // Now get native URI & $_GET parameters
613 $old_default_uri = home_url('/') . Permalink_Manager_Helper_Functions::get_uri($object_id, 'native');
614 $correct_uri = str_replace($old_default_uri, $uri, $request_uri);
615
616 // Fix redirection loop and .html suffix issues
617 if(substr($correct_uri, -1) != '/' && substr($correct_uri, -4) != 'html') {
618 $correct_uri .= '/';
619 } else if(substr($correct_uri, -5) == 'html/') {
620 $correct_uri = strstr($correct_uri, '.html', true) . '.html';
621 }
622
623 if (isset($_REQUEST['debug_redirect'])) {
624 wp_die("<strong>ID:</strong> {$object_id}<br /> <strong>URI:</strong> {$uri}<br/> <strong>Default URI:</strong> {$old_default_uri}<br /><strong>Correct URI:</strong> {$correct_uri}<br /><strong>Request URI</strong>{$request_uri}");
625 // Redirect if it is old URI
626 } else if(strpos($request_uri, $old_default_uri) !== false && ($redirects_activated == 1)) {
627 wp_redirect( $correct_uri, 301 );
628 exit();
629 }
630
631 }
632
633 /**
634 * Allow to edit URIs from "Edit Post" admin pages
635 */
636 function edit_uri_box($html, $id, $new_title, $new_slug) {
637
638 global $post;
639
640 // Do not change anything if post is not saved yet
641 if(empty($post->post_name)) return $html;
642
643 $uris = $this->permalink_manager_uris;
644 $default_uri = trim(str_replace(home_url("/"), "", get_permalink($id)), "/");
645 $uri = (isset($uri[$id])) ? $uri[$id] : $default_uri;
646
647 $html = preg_replace("/(<strong>(.*)<\/strong>)(.*)/is", "$1 ", $html);
648 $html .= home_url("/") . " <span id=\"editable-post-name\"><input type='text' value='{$uri}' name='custom_uri'/></span>";
649 return $html;
650 }
651
652 /**
653 * Update URI from "Edit Post" admin page
654 */
655 function update_single_uri($post_id, $post, $update) {
656
657 // Ignore trashed items
658 if($post->post_status == 'trash') return;
659
660 // Fix for revisions
661 $is_revision = wp_is_post_revision($post_id);
662 $post_id = ($is_revision) ? $is_revision : $post_id;
663 $post = get_post($post_id);
664
665 $uris = $this->permalink_manager_uris;
666
667 $old_default_uri = Permalink_Manager_Helper_Functions::get_uri($post, 'native');
668 $old_uri = (isset($uris[$post->ID])) ? $uris[$post->ID] : $old_default_uri;
669
670 $new_default_uri = Permalink_Manager_Helper_Functions::get_uri($post, true);
671 $new_uri = '';
672
673 // Check if user changed URI (available after post is saved)
674 if(isset($_POST['custom_uri'])) {
675 $new_uri = trim($_POST['custom_uri'], "/");
676 }
677
678 // A little hack (if user removes whole URI from input)
679 $new_uri = ($new_uri) ? $new_uri : $new_default_uri;
680
681 // Do not store default values
682 if(isset($uris[$post->ID]) && ($new_uri == $old_default_uri)) {
683 unset($uris[$post->ID]);
684 } else if ($new_uri != $old_default_uri) {
685 $uris[$post->ID] = $new_uri;
686 }
687
688
689 update_option('permalink-manager-uris', $uris);
690 }
691
692 /**
693 * Remove URI from options array after post is moved to the trash
694 */
695 function remove_single_uri($post_id) {
696 $uris = $this->permalink_manager_uris;
697
698 // Check if the custom permalink is assigned to this post
699 if(isset($uris[$post_id])) {
700 unset($uris[$post_id]);
701 }
702
703 update_option('permalink-manager-uris', $uris);
704 }
705
706 /**
707 * Debug helper function
708 */
709 function debug_functions() {
710 global $wp_filter;
711
712 if(isset($_REQUEST['debug_filter'])) {
713 $hook = $_REQUEST['debug_filter'];
714 $debug_txt = ($_REQUEST['debug_filter'] == "all") ? json_encode($wp_filter) : json_encode($wp_filter[$hook]);
715 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
716 wp_die($debug_txt);
717 } else if(isset($_REQUEST['debug_options'])) {
718 $options = get_option($_REQUEST['debug_options']);
719 $debug_txt = print_r($options, true);
720 $debug_txt = "<textarea style=\"width:100%;height:300px\">{$debug_txt}</textarea>";
721 wp_die($debug_txt);
722 }
723 }
724
725 /**
726 * Convert old plugin structure to the new solution (this function will be removed in 1.0 version)
727 */
728 function upgrade_plugin() {
729
730 global $wpdb;
731
732 /*
733 * Separate slugs from rest of plugin options
734 */
735 $options = $this->permalink_manager_options;
736 //if !empty($this->permalink_manager_options['base-editor'])
737 if (isset($options['base-editor']) && is_array($options['base-editor'])) {
738 $old_permastructs = $options['base-editor'];
739 $new_permastructs = $uris = array();
740
741 // At first save permastructs to new separate option field
742 foreach($old_permastructs as $post_type => $permastruct) {
743 $new_permastructs[$post_type] = trim(str_replace(Permalink_Manager_Helper_Functions::get_post_tag($post_type), '', $permastruct), "/");
744 }
745 unset($options['base-editor']);
746
747 // Grab posts from database
748 $sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ('publish') LIMIT 99999";
749 $posts = $wpdb->get_results($sql_query);
750
751 foreach($posts as $post) {
752 $uri = Permalink_Manager_Helper_Functions::get_uri($post, true);
753
754 // Do not save default permastructures
755 $default_permastruct = trim( Permalink_Manager_Helper_Functions::get_default_permastruct($post_type), "/" );
756 if ($permastruct != $default_permastruct) $uris[$post->ID] = trim($uri, "/");
757 }
758
759 // Save new option fields
760 update_option('permalink-manager-uris', $uris);
761 update_option('permalink-manager', $options);
762 update_option('permalink-manager-permastructs', $new_permastructs);
763
764 // Reset rewrite rules
765 flush_rewrite_rules();
766 }
767 }
768 }
769
770 /**
771 * Begins execution of the plugin.
772 */
773 function run_permalink_manager() {
774
775 // Load plugin files.
776 require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-editor.php';
777 require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-base-editor.php';
778 require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-screen-options.php';
779 require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-helper-functions.php';
780 require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-actions.php';
781
782 $Permalink_Manager_Class = new Permalink_Manager_Class();
783 $Permalink_Manager_Screen_Options = new Permalink_Manager_Screen_Options();
784
785 }
786
787 run_permalink_manager();
788