Permalink Manager Lite - Version 0.3

Version Description

  • Now all permalink parts can be edited - new "Permalink Base Editor" section added.
  • Code optimization.
  • Bugfixes for Screen Options & Edit links.
Download this release

Release Info

Developer mbis
Plugin Icon 128x128 Permalink Manager Lite
Version 0.3
Comparing to
See all releases

Code changes from version 0.2 to 0.3

README.md DELETED
@@ -1,2 +0,0 @@
1
- # Permalink-Manager
2
- A simple tool that helps managing the slugs for Posts, Pages and Custom Post Types.
 
 
README.txt CHANGED
@@ -2,25 +2,28 @@
2
  Contributors: mbis
3
  Tags: urls, permalinks, slugs
4
  Requires at least: 4.0
5
- Tested up to: 4.4
6
- Stable tag: 0.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
- Permalink Manager allows you to control and reset the permalinks (slugs) in all your post types.
11
 
12
  == Description ==
13
 
14
- It is a really simple plugin that helps managing the permalinks that are used for all your Posts, Pages and other Custom Post Types. To improve the experience of the manager, you can filter the table and display only selected `post type`s or posts/pages/custom post type items with particular `post status`es.
 
 
15
 
16
- There are three main functionalities of this plugin:
17
  1. You can manually adjust the slugs of selected posts/pages/custom post type items.
18
  2. You can replace particular (sub)string that is a part of slug with another (sub)string.
19
  3. You can regenerate/reset the slugs for your posts/pages/custom post types. This might be especially useful if your post titles are updated and slugs needs to be recreated.
 
20
 
21
  = Example =
22
 
23
- If you want to quickly replace a part of slug (eg. `krakow` with another word `gdansk`):
 
24
  `http://example.com/hotels-in-krakow
25
  http://example.com/restaurants-in-krakow
26
  http://example.com/transport-in-krakow
@@ -30,7 +33,7 @@ http://example.com/poland/cities/stalowa-wola
30
  http://example.com/poland/cities/warszawa
31
  http://example.com/poland/cities/poznan`
32
 
33
- If you use the form from `Find and replace` section your URLs will be changed to:
34
 
35
  `http://example.com/hotels-in-gdansk
36
  http://example.com/restaurants-in-gdansk
@@ -52,11 +55,11 @@ In the next version of plugin more functionalities will be added:
52
 
53
  == Installation ==
54
 
55
- Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`.
56
 
57
  You can also install this plugin manually:
58
 
59
- 1. Download the plugin's ZIP archive and unzip it.
60
  2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory.
61
  3. Activate the plugin through the 'Plugins' menu in WordPress
62
 
@@ -67,9 +70,15 @@ After the plugin is installed you can access its dashboard from this page: `Tool
67
  1. Main dashboard.
68
  2. Find and replace section.
69
  3. Regenerate section.
 
70
 
71
  == Changelog ==
72
 
 
 
 
 
 
73
  = 0.2 =
74
  * First public version.
75
 
@@ -82,4 +91,4 @@ After the plugin is installed you can access its dashboard from this page: `Tool
82
  Few bugs & strict standard errors are fixed.
83
 
84
  = 0.1 =
85
- A first initial version.
2
  Contributors: mbis
3
  Tags: urls, permalinks, slugs
4
  Requires at least: 4.0
5
+ Tested up to: 4.5
6
+ Stable tag: 0.3
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
+ Edit, mass replace or regenerate the permalinks (slugs) in all post types. You can also adjust their default permastructures (permalink bases/fronts).
11
 
12
  == Description ==
13
 
14
+ It is a really simple plugin that helps managing the permalinks that are used for all your Posts, Pages and other Custom Post Types. To improve the experience of the manager, you can filter the table and display only selected `post type`s or posts/pages/custom post type items with particular `post status`es.
15
+
16
+ There are four main functionalities of this plugin:
17
 
 
18
  1. You can manually adjust the slugs of selected posts/pages/custom post type items.
19
  2. You can replace particular (sub)string that is a part of slug with another (sub)string.
20
  3. You can regenerate/reset the slugs for your posts/pages/custom post types. This might be especially useful if your post titles are updated and slugs needs to be recreated.
21
+ 4. You can change the default permalink bases (permastructures) for all custom post types & posts and pages (experimental functionality).
22
 
23
  = Example =
24
 
25
+ If you want to quickly replace a part of slug (eg. `krakow` with another word `gdansk`), you just need to use the form from `Find and replace` section:
26
+
27
  `http://example.com/hotels-in-krakow
28
  http://example.com/restaurants-in-krakow
29
  http://example.com/transport-in-krakow
33
  http://example.com/poland/cities/warszawa
34
  http://example.com/poland/cities/poznan`
35
 
36
+ After using it your permalinks will be changed to:
37
 
38
  `http://example.com/hotels-in-gdansk
39
  http://example.com/restaurants-in-gdansk
55
 
56
  == Installation ==
57
 
58
+ Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`.
59
 
60
  You can also install this plugin manually:
61
 
62
+ 1. Download the plugin's ZIP archive and unzip it.
63
  2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory.
64
  3. Activate the plugin through the 'Plugins' menu in WordPress
65
 
70
  1. Main dashboard.
71
  2. Find and replace section.
72
  3. Regenerate section.
73
+ 4. Experimental function - Permalink Base (Permastructure) Editor.
74
 
75
  == Changelog ==
76
 
77
+ = 0.3 =
78
+ * Now all permalink parts can be edited - new "Permalink Base Editor" section added.
79
+ * Code optimization.
80
+ * Bugfixes for Screen Options & Edit links.
81
+
82
  = 0.2 =
83
  * First public version.
84
 
91
  Few bugs & strict standard errors are fixed.
92
 
93
  = 0.1 =
94
+ A first initial version.
css/permalink-manager-admin.css CHANGED
@@ -5,19 +5,21 @@
5
 
6
  #permalinks-table-wrap #plugin-name-heading a { color: #959595; font-size: 60%; text-decoration: none; }
7
 
8
- #permalinks-table-wrap .tablenav { margin: 6px 0 15px; }
9
- #permalinks-table-wrap .column-post_type { width: 10%; }
10
- #permalinks-table-wrap .column-post_permalink { width: 50%; }
11
- #permalinks-table-wrap .post_name input { max-width: 100%; }
12
  #permalinks-table-wrap .post_permalink a, #permalinks-table-wrap .post_permalink .dashicons { font-size: 13px; color: #aaa; line-height: 1.5em; }
13
-
14
  #permalinks-table-wrap .alert { line-height: 19px; padding: 11px 15px; margin: 15px 0; }
15
- #permalinks-table-wrap .alert p { margin-top: 0; }
16
- #permalinks-table-wrap .alert p:last-of-type { margin-bottom: 0; }
17
- #permalinks-table-wrap .warning { background: #dc3232; color: #fff; }
 
 
18
  #permalinks-table-wrap .info { background: #f9f9f9; }
19
-
20
  #permalinks-table-wrap #permalink-manager-tabs > div { display: none; }
21
  #permalinks-table-wrap #permalink-manager-tabs > div.show { display: block; }
22
 
23
- #permalinks-table-wrap #permalink-manager-tabs td label { display: block; }
5
 
6
  #permalinks-table-wrap #plugin-name-heading a { color: #959595; font-size: 60%; text-decoration: none; }
7
 
8
+ #permalinks-table-wrap .tablenav { margin: 6px 0 15px; }
9
+ #permalinks-table-wrap .column-post_type { width: 10%; }
10
+ #permalinks-table-wrap .column-post_permalink { width: 50%; }
11
+ #permalinks-table-wrap .post_name input { max-width: 100%; }
12
  #permalinks-table-wrap .post_permalink a, #permalinks-table-wrap .post_permalink .dashicons { font-size: 13px; color: #aaa; line-height: 1.5em; }
13
+
14
  #permalinks-table-wrap .alert { line-height: 19px; padding: 11px 15px; margin: 15px 0; }
15
+ #permalinks-table-wrap .alert p { margin-top: 0; line-height: 200%; }
16
+ #permalinks-table-wrap .alert ul, #permalinks-table-wrap .alert ol { margin-top: 0; margin-bottom: 0; }
17
+ #permalinks-table-wrap .alert p:last-of-type, #permalinks-table-wrap .alert li:last-of-type { margin-bottom: 0; }
18
+ #permalinks-table-wrap .warning { background: #dc3232; }
19
+ #permalinks-table-wrap .warning, #permalinks-table-wrap .warning a { color: #fff; }
20
  #permalinks-table-wrap .info { background: #f9f9f9; }
21
+
22
  #permalinks-table-wrap #permalink-manager-tabs > div { display: none; }
23
  #permalinks-table-wrap #permalink-manager-tabs > div.show { display: block; }
24
 
25
+ #permalinks-table-wrap #permalink-manager-tabs td label { display: block; }
inc/permalink-manager-base-editor.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( ! class_exists( 'WP_List_Table' ) ) {
3
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
4
+ }
5
+
6
+ /**
7
+ * Create a new table class that will extend the WP_List_Table
8
+ */
9
+ class Permalink_Manager_Base_Editor extends WP_List_Table {
10
+ public $screen_options_fields;
11
+
12
+ function __construct() {
13
+ global $status, $page;
14
+
15
+ parent::__construct(array(
16
+ 'singular' => 'slug',
17
+ 'plural' => 'slugs',
18
+ 'ajax' => true
19
+ ));
20
+ }
21
+
22
+ /**
23
+ * Override the parent columns method. Defines the columns to use in your listing table
24
+ */
25
+ public function get_columns() {
26
+ $columns = array(
27
+ //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
28
+ 'post_type' => __('Post Type', 'permalink-manager'),
29
+ 'post_permalink_base' => __('Permalink Base/Permastructure', 'permalink-manager'),
30
+ 'post_type_structure_tag' => __('Permalink Base Should End With', 'permalink-manager'),
31
+ 'post_type_default_base' => __('Default Permalink Base/Permastructure', 'permalink-manager'),
32
+ //'post_sample_permalink' => __('Sample Permalink', 'permalink-manager')
33
+ );
34
+
35
+ return $columns;
36
+ }
37
+
38
+ /**
39
+ * Hidden columns
40
+ */
41
+ public function get_hidden_columns() {
42
+ return array('post_date_gmt');
43
+ }
44
+
45
+ /**
46
+ * Sortable columns
47
+ */
48
+ public function get_sortable_columns() {
49
+ return array(
50
+ 'post_type' => array('post_title', false),
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Data inside the columns
56
+ */
57
+ public function column_default( $item, $column_name ) {
58
+ $permastruct = Permalink_Manager_Helper_Functions::get_permastruct($item['name'], false);
59
+ $default_permastruct = Permalink_Manager_Helper_Functions::get_permastruct($item['name'], false, 'default_permastruct');
60
+
61
+ switch( $column_name ) {
62
+ case 'post_type':
63
+ return "{$item['label']}<br /><small>({$item['name']})</small>";
64
+
65
+ case 'post_permalink_base':
66
+ $placeholder = $default_permastruct;
67
+ $field_args = array('type' => 'text', 'default' => $permastruct, 'without_label' => true, 'input_class' => 'widefat', 'placeholder' => $placeholder);
68
+ return Permalink_Manager_Helper_Functions::generate_option_field($item['name'], $field_args, 'base-editor');
69
+
70
+ case 'post_type_default_base':
71
+ return "<code>{$default_permastruct}</code>";
72
+
73
+ case 'post_type_structure_tag':
74
+ return "<code>" . Permalink_Manager_Helper_Functions::get_post_tag($item['name']) . "</code>";
75
+
76
+ default:
77
+ return '';
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Sort the data
83
+ */
84
+ private function sort_data( $a, $b ) {
85
+ // Set defaults
86
+ $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
87
+ $result = strnatcasecmp( $a['name'], $b['name'] );
88
+
89
+ return ($order === 'asc') ? $result : -$result;
90
+ }
91
+
92
+ /**
93
+ * The button that allows to save updated slugs
94
+ */
95
+ function extra_tablenav( $which ) {
96
+ $save_button = __( 'Save settings', 'permalink-manager' );
97
+ $flush_button = __( 'Flush rewrite rules', 'permalink-manager' );
98
+
99
+ echo '<div class="alignleft actions">';
100
+ submit_button( $save_button, 'primary', "save_permalink_structures[{$which}]", false, array( 'id' => 'doaction', 'value' => 'save_permalink_structures' ) );
101
+ submit_button( $flush_button, 'primary', "flush_rewrite_rules[{$which}]", false, array( 'id' => 'doaction', 'value' => 'flush_rewrite_rules' ) );
102
+ echo '</div>';
103
+ }
104
+
105
+ /**
106
+ * Prepare the items for the table to process
107
+ */
108
+ public function prepare_items($posts_table) {
109
+ $columns = $this->get_columns();
110
+ $hidden = $this->get_hidden_columns();
111
+ $sortable = $this->get_sortable_columns();
112
+ $currentPage = $this->get_pagenum();
113
+
114
+ global $wpdb;
115
+
116
+ // Load options and fields
117
+ $saved_options = get_option('permalink-manager');
118
+ $screen_options_fields = $this->screen_options_fields;
119
+ $per_page = isset($saved_options['per_page']) ? $saved_options['per_page'] : $screen_options_fields['per_page']['default'];
120
+
121
+ // Load all post types
122
+ $data = Permalink_Manager_Helper_Functions::get_post_types_array('full');
123
+
124
+ // Attachments are excluded
125
+ unset($data['attachment']);
126
+
127
+ // Will be used in pagination settings
128
+ $total_items = count($data);
129
+
130
+ // SQL query parameters
131
+ $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
132
+ $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
133
+ $offset = ($currentPage - 1) * $per_page;
134
+
135
+ // Sort posts and count all posts
136
+ usort( $data, array( &$this, 'sort_data' ) );
137
+
138
+ // Pagination
139
+ $data = array_slice($data, $offset, $per_page);
140
+
141
+ $this->set_pagination_args( array(
142
+ 'total_items' => $total_items,
143
+ 'per_page' => $per_page
144
+ ));
145
+
146
+ $this->_column_headers = array($columns, $hidden, $sortable);
147
+ $this->items = $data;
148
+ }
149
+
150
+ /**
151
+ * This variable is assigned in permalink-manager.php before prepare_items() function is triggered, see permalinks_table_html() function
152
+ */
153
+ public function set_screen_option_fields($fields) {
154
+ $this->screen_options_fields = $fields;
155
+ }
156
+
157
+ }
158
+ ?>
inc/permalink-manager-helper-functions.php CHANGED
@@ -5,99 +5,233 @@
5
  */
6
 
7
  class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
8
-
9
- public function __construct() {
10
- parent::construct();
11
- }
12
-
13
  /**
14
  * Display error/info message
15
  */
16
- static function display_alert($content, $type) {
17
- return sprintf( "<div class='{$type} is-dismissible notice'><p> %s </p></div>", $content );
 
 
 
 
 
 
 
 
18
  }
19
-
20
  /**
21
  * Display the permalink in a better way
22
  */
23
  static function get_correct_permalink($id, $correct_slug, $highlight = false) {
24
  $output = get_permalink($id);
25
-
26
  // Get last part of URI
27
- $old_slug = end((explode('/', get_page_uri($id))));
28
  $correct_slug = ($highlight) ? "<code>{$correct_slug}</code>" : $correct_slug;
29
  $output = Permalink_Manager_Helper_Functions::str_lreplace($old_slug, $correct_slug, $output);
30
-
31
  return $output;
32
  }
33
-
34
  /**
35
  * Get post_types array
36
  */
37
- static function get_post_types_array() {
38
- $post_types = get_post_types( array('public' => true), 'objects' );
39
-
40
- $post_types_array = array();
41
- foreach ( $post_types as $post_type ) {
42
- $post_types_array[$post_type->name] = $post_type->labels->name;
43
- }
44
 
45
- return $post_types_array;
 
 
 
 
 
 
 
 
46
  }
47
-
 
 
 
48
  /**
49
  * Replace last occurence
50
  */
51
  static function str_lreplace($search, $replace, $subject) {
52
- $pos = strrpos($subject, $search);
53
- return ($pos !== false) ? substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
54
  }
55
-
56
- /**
57
- * Generate the fields
58
- */
59
- static public function generate_option_field($name, $args, $group) {
60
-
61
  // Load values from options if needed
62
- //$saved_values = (in_array($group, array('screen-options', 'find-replace'))) ? get_option('permalink-manager') : '';
63
- $saved_values = get_option('permalink-manager');
64
-
65
  // Reset $fields variable
66
  $fields = '';
67
-
68
  // Load default value
69
  $default_value = (isset($args['default'])) ? $args['default'] : '';
70
-
71
- switch($args['type']) {
 
 
 
 
72
  case 'checkbox' :
73
  $fields .= '<div class="checkboxes">';
74
  foreach($args['choices'] as $value => $label) {
75
- $all_checked = (isset($saved_values[$name])) ? $saved_values[$name] : $args['default'];
76
- $checked = in_array($value, $all_checked) ? "checked='checked'" : "";
77
- $fields .= "<label for='permalink-manager[{$group}][{$name}][]'><input type='checkbox' value='{$value}' name='permalink-manager[{$group}][{$name}][]' {$checked} /> {$label}</label>";
78
  }
79
  $fields .= '</div>';
80
  break;
 
81
  case 'number' :
82
- $value = (isset($saved_values[$name])) ? $saved_values[$name] : $default_value;
83
- $fields .= "<input type='number' value='{$value}' name='permalink-manager[{$group}][{$name}]' />";
84
  break;
85
- default :
86
- $value = (isset($saved_values[$name])) ? $saved_values[$name] : $default_value;
87
- $fields .= "<input type='text' value='{$value}' name='permalink-manager[{$group}][{$name}]' />";
 
88
  }
89
-
90
  // Get all variables into one final variable
91
  if(isset($group) && !($group === 'screen-options')) {
92
- $output = "<legend>{$args['label']}</legend>";
93
  $output .= "<div class='metabox-prefs'><div class='{$name}-container'>{$fields}</div></div>";
94
- } else {
95
- $output = "<tr><th><label for='permalink-manager[{$name}]'>{$args['label']}</label></th>";
 
 
96
  $output .= "<td>{$fields}</td>";
97
  }
98
-
99
- return $output;
100
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  }
102
-
103
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  */
6
 
7
  class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
8
+
9
+ public function __construct() {}
10
+
 
 
11
  /**
12
  * Display error/info message
13
  */
14
+ static function display_alert($alert_content, $alert_type, $before_tabs = false) {
15
+ $output = sprintf( "<div class='{$alert_type} is-dismissible notice'><p> %s </p></div>", $alert_content );
16
+
17
+ if($before_tabs) {
18
+ add_filter('permalink-manager-before-tabs', function( $arg ) use ( $output ) {
19
+ return $output;
20
+ });
21
+ } else {
22
+ return $output;
23
+ }
24
  }
25
+
26
  /**
27
  * Display the permalink in a better way
28
  */
29
  static function get_correct_permalink($id, $correct_slug, $highlight = false) {
30
  $output = get_permalink($id);
31
+
32
  // Get last part of URI
33
+ $old_slug = end((explode('/', get_page_uri($id))));
34
  $correct_slug = ($highlight) ? "<code>{$correct_slug}</code>" : $correct_slug;
35
  $output = Permalink_Manager_Helper_Functions::str_lreplace($old_slug, $correct_slug, $output);
36
+
37
  return $output;
38
  }
39
+
40
  /**
41
  * Get post_types array
42
  */
43
+ static function get_post_types_array($format = null, $cpt = null) {
44
+ $post_types = get_post_types( array('public' => true), 'objects' );
 
 
 
 
 
45
 
46
+ $post_types_array = array();
47
+ if($format == 'full') {
48
+ foreach ( $post_types as $post_type ) {
49
+ $post_types_array[$post_type->name] = array('label' => $post_type->labels->name, 'name' => $post_type->name);
50
+ }
51
+ } else {
52
+ foreach ( $post_types as $post_type ) {
53
+ $post_types_array[$post_type->name] = $post_type->labels->name;
54
+ }
55
  }
56
+
57
+ return (empty($cpt)) ? $post_types_array : $post_types_array[$cpt];
58
+ }
59
+
60
  /**
61
  * Replace last occurence
62
  */
63
  static function str_lreplace($search, $replace, $subject) {
64
+ $pos = strrpos($subject, $search);
65
+ return ($pos !== false) ? substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
66
  }
67
+
68
+ /**
69
+ * Generate the fields
70
+ */
71
+ static public function generate_option_field($name, $args, $group = null) {
 
72
  // Load values from options if needed
73
+ $saved_values = get_option('permalink-manager');
74
+
 
75
  // Reset $fields variable
76
  $fields = '';
77
+
78
  // Load default value
79
  $default_value = (isset($args['default'])) ? $args['default'] : '';
80
+ $label = (isset($args['label'])) ? $args['label'] : '';
81
+ $placeholder = (isset($args['placeholder'])) ? "placeholder=\"{$args['placeholder']}\"" : '';
82
+ $input_class = (isset($args['input_class'])) ? "class=\"{$args['input_class']}\"" : '';
83
+ $input_name = ($group) ? "permalink-manager[{$group}][{$name}]" : $name;
84
+
85
+ switch($args['type']) {
86
  case 'checkbox' :
87
  $fields .= '<div class="checkboxes">';
88
  foreach($args['choices'] as $value => $label) {
89
+ $all_checked = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $args['default'];
90
+ $checked = in_array($value, $all_checked) ? "checked='checked'" : "";
91
+ $fields .= "<label for='{$input_name}[]'><input type='checkbox' {$input_class} value='{$value}' name='{$input_name}[]' {$checked} /> {$label}</label>";
92
  }
93
  $fields .= '</div>';
94
  break;
95
+
96
  case 'number' :
97
+ $value = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $default_value;
98
+ $fields .= "<input type='number' {$input_class} value='{$value}' name='{$input_name}' />";
99
  break;
100
+
101
+ default :
102
+ $value = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $default_value;
103
+ $fields .= "<input type='text' {$input_class} value='{$value}' name='{$input_name}' {$placeholder}/>";
104
  }
105
+
106
  // Get all variables into one final variable
107
  if(isset($group) && !($group === 'screen-options')) {
108
+ $output = "<legend>{$label}</legend>";
109
  $output .= "<div class='metabox-prefs'><div class='{$name}-container'>{$fields}</div></div>";
110
+ } else if (isset($args['without_label']) && $args['without_label'] == true) {
111
+ $output = $fields;
112
+ } else {
113
+ $output = "<tr><th><label for='{$input_name}'>{$args['label']}</label></th>";
114
  $output .= "<td>{$fields}</td>";
115
  }
116
+
117
+ return $output;
118
+ }
119
+
120
+ /**
121
+ * Check if the provided slug is unique and then update it with SQL query.
122
+ */
123
+ static function update_slug_by_id($slug, $id) {
124
+ global $wpdb;
125
+
126
+ // Update slug and make it unique
127
+ $slug = (empty($slug)) ? sanitize_title(get_the_title($id)) : $slug;
128
+ $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
129
+ $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
130
+
131
+ return $new_slug;
132
+ }
133
+
134
+ /**
135
+ * Save option
136
+ */
137
+ static function save_option($field = null, $value = null) {
138
+ $options = get_option('permalink-manager', array());
139
+ if($field) {
140
+ $options[$field] = $value;
141
+
142
+ // The snippet belows prevent duplicates in permastructures
143
+ if($field == 'base-editor') {
144
+
145
+ //print_r($value);
146
+
147
+ // Algorithm below works like array_count_values(), but we also need to make the permastructs unique
148
+ $unique_permastructures = array();
149
+ foreach($value as $key => $permastruct) {
150
+ // Trim whitespaces & slashes at first
151
+ $permastruct = trim(trim($permastruct, "/"));
152
+
153
+ // The permastruct is not unique!
154
+ if(empty($permastruct)) {
155
+ $permastruct = Permalink_Manager_Helper_Functions::get_permastruct($key, false, 'default_permastruct');
156
+ } else if(isset($unique_permastructures[$permastruct])) {
157
+ $unique_permastructures[$permastruct]++;
158
+ // Alter the permastruct
159
+ $permastruct = "{$key}/{$permastruct}";
160
+ } else {
161
+ $unique_permastructures[$permastruct] = 1;
162
+ }
163
+
164
+ // Trim one more time
165
+ $permastruct = trim(trim($permastruct, "/"));
166
+
167
+ // Alter the permastruct
168
+ $options[$field][$key] = $permastruct;
169
+ }
170
+
171
+ }
172
+
173
+ update_option('permalink-manager', $options);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Get permastruct
179
+ */
180
+ static function get_permastruct($post_type = 'page', $title_replace = false, $return = 'permastruct') {
181
+ global $wp_rewrite;
182
+
183
+ // Load permastruct from options
184
+ $options = get_option('permalink-manager', array());
185
+ $permastructs = $options['base-editor'];
186
+
187
+ // Get default permastruct
188
+ if($post_type == 'page') {
189
+ $default_permastruct = $wp_rewrite->get_page_permastruct();
190
+ } else if($post_type == 'post') {
191
+ $default_permastruct = get_option('permalink_structure');
192
+ } else {
193
+ $default_permastruct = $wp_rewrite->get_extra_permastruct($post_type);
194
  }
195
+
196
+ // If the permastruct is not saved for post type or empty return default permastruct
197
+ $permastruct = (isset($permastructs[$post_type]) && $permastructs[$post_type]) ? $permastructs[$post_type] : $default_permastruct;
198
+
199
+ // Remove post name to enable support for hierarchical post types
200
+ $permastruct = ($title_replace) ? str_replace(array("%pagename%", "%postname%", "%{$post_type}%"), '', $permastruct) : "";
201
+
202
+ return trim($$return, '/');
203
+ }
204
+
205
+ /**
206
+ * Structure Tags & Rewrite functions
207
+ */
208
+ static function get_all_structure_tags($code = true, $seperator = ', ') {
209
+ global $wp_rewrite;
210
+
211
+ $tags = $wp_rewrite->rewritecode;
212
+ $output = "";
213
+ $last_tag_index = count($tags);
214
+ $i = 1;
215
+
216
+ foreach($tags as $tag) {
217
+ $sep = ($last_tag_index == $i) ? "" : $seperator;
218
+ $output .= ($code) ? "<code>{$tag}</code>{$sep}" : "{$tag}{$sep}";
219
+ $i++;
220
+ }
221
+
222
+ return $output;
223
+ }
224
+
225
+ static function get_post_tag($post_type) {
226
+ // Get the post type (with fix for posts & pages)
227
+ if($post_type == 'page') {
228
+ $post_type_tag = '%pagename%';
229
+ } else if ($post_type == 'post') {
230
+ $post_type_tag = '%postname%';
231
+ } else {
232
+ $post_type_tag = "%{$post_type}%";
233
+ }
234
+ return $post_type_tag;
235
+ }
236
+
237
+ }
inc/permalink-manager-screen-options.php CHANGED
@@ -5,42 +5,36 @@
5
  */
6
 
7
  class Permalink_Manager_Screen_Options extends Permalink_Manager_Class {
8
-
9
  public function __construct() {
10
-
11
- $admin_page = PERMALINK_MANAGER_MENU_PAGE;
 
12
  add_action( "load-{$admin_page}", array($this, "save_screen_options") );
13
  add_filter( "screen_settings", array($this, "add_screen_options") );
14
-
15
  }
16
-
17
  /**
18
  * Add scren options
19
  */
20
  public function add_screen_options() {
21
-
22
- $button = get_submit_button( __( 'Apply', 'permalink-manager' ), 'primary', 'screen-options-apply', false );
23
- $return = "<fieldset>";
24
-
25
- foreach(parent::fields_arrays('screen_options') as $field_name => $field_args) {
26
-
27
- $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'screen-options');
28
-
29
- }
30
-
31
- $return .= "</fieldset><br class='clear'>{$button}";
32
-
33
- return $return;
34
-
35
  }
36
-
37
  /**
38
  * Save fields
39
  */
40
  public function save_screen_options() {
41
-
42
- if(isset($_POST['screen-options-apply'])) update_option('permalink-manager', $_POST['permalink-manager']['screen-options']);
43
-
44
  }
45
-
46
- }
5
  */
6
 
7
  class Permalink_Manager_Screen_Options extends Permalink_Manager_Class {
8
+
9
  public function __construct() {
10
+ $admin_page = PERMALINK_MANAGER_MENU_PAGE;
11
+
12
+ if(isset($_GET['page']) && $_GET['page'] == 'permalink-manager.php') {
13
  add_action( "load-{$admin_page}", array($this, "save_screen_options") );
14
  add_filter( "screen_settings", array($this, "add_screen_options") );
15
+ }
16
  }
17
+
18
  /**
19
  * Add scren options
20
  */
21
  public function add_screen_options() {
22
+ $button = get_submit_button( __( 'Apply', 'permalink-manager' ), 'primary', 'screen-options-apply', false );
23
+ $return = "<fieldset>";
24
+
25
+ foreach(parent::fields_arrays('screen_options') as $field_name => $field_args) {
26
+ $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'screen-options');
27
+ }
28
+
29
+ $return .= "</fieldset><br class='clear'>{$button}";
30
+ return $return;
 
 
 
 
 
31
  }
32
+
33
  /**
34
  * Save fields
35
  */
36
  public function save_screen_options() {
37
+ if(isset($_POST['screen-options-apply'])) Permalink_Manager_Helper_Functions::save_option('screen-options', $_POST['permalink-manager']['screen-options']);
 
 
38
  }
39
+
40
+ }
inc/permalink-manager-slug-editor.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( ! class_exists( 'WP_List_Table' ) ) {
3
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
4
+ }
5
+
6
+ /**
7
+ * Create a new table class that will extend the WP_List_Table
8
+ */
9
+ class Permalink_Manager_Slug_Editor extends WP_List_Table {
10
+ public $screen_options_fields;
11
+
12
+ function __construct() {
13
+ global $status, $page;
14
+
15
+ parent::__construct(array(
16
+ 'singular' => 'slug',
17
+ 'plural' => 'slugs',
18
+ 'ajax' => true
19
+ ));
20
+ }
21
+
22
+ /**
23
+ * Override the parent columns method. Defines the columns to use in your listing table
24
+ */
25
+ public function get_columns() {
26
+ $columns = array(
27
+ //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
28
+ 'post_title' => __('Title', 'permalink-manager'),
29
+ 'post_name' => __('Slug', 'permalink-manager'),
30
+ 'post_date_gmt' => __('Date', 'permalink-manager'),
31
+ 'post_permalink' => __('Permalink', 'permalink-manager'),
32
+ 'post_status' => __('Post Status', 'permalink-manager'),
33
+ 'post_type' => __('Post Type', 'permalink-manager')
34
+ );
35
+
36
+ return $columns;
37
+ }
38
+
39
+ /**
40
+ * Hidden columns
41
+ */
42
+ public function get_hidden_columns() {
43
+ return array('post_date_gmt');
44
+ }
45
+
46
+ /**
47
+ * Sortable columns
48
+ */
49
+ public function get_sortable_columns() {
50
+ return array(
51
+ 'post_title' => array('post_title', false),
52
+ 'post_name' => array('post_name', false),
53
+ 'post_status' => array('post_status', false),
54
+ 'post_type' => array('post_type', false),
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Data inside the columns
60
+ */
61
+ public function column_default( $item, $column_name ) {
62
+ switch( $column_name ) {
63
+ case 'post_type':
64
+ $post_type_labels = Permalink_Manager_Helper_Functions::get_post_types_array('full', $item['post_type']);
65
+ return "{$post_type_labels['label']}<br /><small>({$post_type_labels['name']})</small>";
66
+
67
+ case 'post_status':
68
+ $post_statuses_array = get_post_statuses();
69
+ return "{$post_statuses_array[$item[ $column_name ]]}<br /><small>({$item[ $column_name ]})</small>";
70
+
71
+ case 'post_permalink':
72
+ return ($item['post_status'] != 'publish') ? '-' : Permalink_Manager_Helper_Functions::get_correct_permalink($item[ 'ID' ], $item[ 'post_name' ], true) . ' <a href="' . Permalink_Manager_Helper_Functions::get_correct_permalink($item[ 'ID' ], $item[ 'post_name' ]) . '" target="_blank"><span class="dashicons dashicons-admin-links"></span></a>';
73
+
74
+ case 'post_name':
75
+ $field_name = "slug[{$item['ID']}]";
76
+ $field_args = array('type' => 'text', 'default' => $item[ 'post_name' ], 'without_label' => true, 'input_class' => 'widefat');
77
+ return Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args);
78
+
79
+ case 'post_title':
80
+ $edit_post = $item[ 'post_title' ] . '<div class="row-actions">';
81
+ $edit_post .= '<span class="edit"><a target="_blank" href="' . home_url() . '/wp-admin/post.php?post=' . $item[ 'ID' ] . '&amp;action=edit" title="' . __('Edit', 'permalink-manager') . '">' . __('Edit', 'permalink-manager') . '</a> | </span>';
82
+ $edit_post .= '<span class="view"><a target="_blank" href="' . Permalink_Manager_Helper_Functions::get_correct_permalink($item[ 'ID' ], $item[ 'post_name' ]) . '" title="' . __('View', 'permalink-manager') . ' ' . $item[ 'post_title' ] . '" rel="permalink">' . __('View', 'permalink-manager') . '</a> | </span>';
83
+ $edit_post .= '<span class="id">#' . $item[ 'ID' ] . '</span>';
84
+ $edit_post .= '</div>';
85
+ return $edit_post;
86
+
87
+ default:
88
+ return $item[ $column_name ];
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Sort the data
94
+ */
95
+ private function sort_data( $a, $b ) {
96
+ // Set defaults
97
+ $orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'post_title';
98
+ $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
99
+ $result = strnatcasecmp( $a[$orderby], $b[$orderby] );
100
+
101
+ return ($order === 'asc') ? $result : -$result;
102
+ }
103
+
104
+ /**
105
+ * The button that allows to save updated slugs
106
+ */
107
+ function extra_tablenav( $which ) {
108
+ $button_top = __( 'Update all slugs below', 'permalink-manager' );
109
+ $button_bottom = __( 'Update all slugs above', 'permalink-manager' );
110
+
111
+ echo '<div class="alignleft actions">';
112
+ submit_button( ${"button_$which"}, 'primary', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
113
+ echo '</div>';
114
+ }
115
+
116
+ /**
117
+ * Prepare the items for the table to process
118
+ */
119
+ public function prepare_items($posts_table) {
120
+ $columns = $this->get_columns();
121
+ $hidden = $this->get_hidden_columns();
122
+ $sortable = $this->get_sortable_columns();
123
+ $currentPage = $this->get_pagenum();
124
+
125
+ global $wpdb;
126
+
127
+ // Load options and fields
128
+ $saved_options = get_option('permalink-manager');
129
+ $saved_options = isset($saved_options['screen-options']) ? $saved_options['screen-options'] : array();
130
+ $screen_options_fields = $this->screen_options_fields;
131
+ $per_page = isset($saved_options['per_page']) ? $saved_options['per_page'] : $screen_options_fields['per_page']['default'];
132
+ $post_types_array = isset($saved_options['post_types']) ? $saved_options['post_types'] : $screen_options_fields['post_types']['default'];
133
+ $post_types = "'" . implode("', '", $post_types_array) . "'";
134
+ $post_statuses_array = isset($saved_options['post_statuses']) ? $saved_options['post_statuses'] : $screen_options_fields['post_statuses']['default'];
135
+ $post_statuses = "'" . implode("', '", $post_statuses_array) . "'";
136
+
137
+ // Will be used in pagination settings
138
+ $total_items = $wpdb->get_var("SELECT COUNT(id) FROM $posts_table WHERE post_status IN ($post_statuses) AND post_type IN ($post_types)");
139
+
140
+ // SQL query parameters
141
+ $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
142
+ $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
143
+ $offset = ($currentPage - 1) * $per_page;
144
+
145
+ // Grab posts from database
146
+ $sql_query = "SELECT * FROM $posts_table WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order LIMIT $per_page OFFSET $offset";
147
+ $data = $wpdb->get_results($sql_query, ARRAY_A);
148
+
149
+ // Sort posts and count all posts
150
+ usort( $data, array( &$this, 'sort_data' ) );
151
+
152
+ $this->set_pagination_args( array(
153
+ 'total_items' => $total_items,
154
+ 'per_page' => $per_page
155
+ ));
156
+
157
+ $this->_column_headers = array($columns, $hidden, $sortable);
158
+ $this->items = $data;
159
+ }
160
+
161
+ /**
162
+ * This variable is assigned in permalink-manager.php before prepare_items() function is triggered, see permalinks_table_html() function
163
+ */
164
+ public function set_screen_option_fields($fields) {
165
+ $this->screen_options_fields = $fields;
166
+ }
167
+
168
+ }
169
+ ?>
permalink-manager.php CHANGED
@@ -4,7 +4,7 @@
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.2.0
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
@@ -20,7 +20,7 @@ if ( ! defined( 'WPINC' ) ) {
20
 
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'permalink-manager' );
23
- define( 'PERMALINK_MANAGER_VERSION', '0.2.0' );
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' );
@@ -29,159 +29,222 @@ 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, $permalink_manager_options_page;
33
 
34
  public function __construct() {
35
 
36
- $this->permalink_manager_options = get_option('permalink-manager');
37
-
38
  add_action( 'plugins_loaded', array($this, 'localize_me') );
39
- add_action( 'admin_init', array($this, 'process_forms') );
 
40
  add_action( 'admin_menu', array($this, 'add_menu_page') );
41
  add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugins_page_links') );
42
-
 
 
 
 
 
43
  }
44
-
45
  /**
46
  * Localize this plugin
47
  */
48
  function localize_me() {
49
  load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
50
  }
51
-
52
  /**
53
  * Add menu page and load CSS & JS.
54
  */
55
  function add_menu_page() {
56
  add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', PERMALINK_MANAGER_OPTIONS_PAGE, array($this, 'list_slugs_admin_page') );
57
-
58
  // Make sure thata the CSS and JS files are loaded only on plugin admin page.
59
  add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_styles' ) );
60
  add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_scripts' ) );
61
  }
62
-
63
  /**
64
  * Display the table with slugs.
65
  */
66
- function permalinks_table_html() {
67
  global $wpdb;
68
-
69
- $Permalink_Manager_Table = new Permalink_Manager_Table();
70
- $Permalink_Manager_Table->set_screen_option_fields($this->fields_arrays('screen_options'));
71
- $Permalink_Manager_Table->prepare_items($wpdb->posts);
72
-
73
  ?>
74
-
75
  <form id="permalinks-table" method="post">
76
- <input type="hidden" name="page" value="<?php echo $_POST['page']; ?>" />
77
- <?php echo $Permalink_Manager_Table->display(); ?>
78
  </form>
79
  <?php
80
  }
81
-
82
  /**
83
  * Mass replace options page.
84
  */
85
  function find_and_replace_html() {
86
  $button = get_submit_button( __( 'Find & Replace', 'permalink-manager' ), 'primary', 'find-replace-button', false );
87
-
88
  $return = "<form id=\"permalinks-table-find-replace\" method=\"post\">";
89
- $return .= "<table class=\"form-table\">";
90
-
91
- foreach($this->fields_arrays('find_replace') as $field_name => $field_args) {
92
- $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'find-replace');
93
- }
94
-
95
- $return .= "</table>{$button}";
 
96
  $return .= "</form>";
97
-
98
  echo $return;
99
  }
100
-
101
  /**
102
  * Reset slugs page.
103
  */
104
- function regenerate_slugs_html() {
105
  $button = get_submit_button( __( 'Regenerate', 'permalink-manager' ), 'primary', 'regenerate-button', false );
106
-
107
  $return = "<form id=\"permalinks-table-regenerate\" method=\"post\">";
 
108
  $return .= "<table class=\"form-table\">";
109
-
110
- foreach($this->fields_arrays('regenerate') as $field_name => $field_args) {
111
- $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'regenerate');
112
  }
113
-
114
  $return .= "</table>{$button}";
115
  $return .= "</form>";
116
-
117
  echo $return;
118
  }
119
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  * Display the plugin dashboard.
122
  */
123
  function list_slugs_admin_page() {
124
  global $wpdb;
125
-
126
  // Check which tab is active now.
127
- $active_tab = ( isset( $_GET[ 'tab' ] ) ) ? $_GET[ 'tab' ] : 'permalinks';
128
-
 
 
 
 
 
 
129
  // Tabs array with assigned functions used to display HTML content.
130
  $tabs = array(
131
- 'permalinks' => array(
132
- 'name' => __('Permalinks', 'permalink-manager'),
133
- 'function' => 'permalinks_table_html',
134
- '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')
135
  ),
136
  'find_and_replace' => array(
137
- 'name' => __('Find and replace', 'permalink-manager'),
138
  'function' => 'find_and_replace_html',
139
- 'warning' => (__('<strong>You are doing it at your own risk!</strong>', 'permalink-manager') . '<br />' . __('A backup of MySQL database before using this tool is highly recommended. The search & replace operation might be not revertible!', 'permalink-manager'))
140
  ),
141
  'regenerate_slugs' => array(
142
- 'name' => __('Regenerate slugs', 'permalink-manager'),
143
  'function' => 'regenerate_slugs_html',
144
- 'warning' => (__('<strong>You are doing it at your own risk!</strong>', 'permalink-manager') . '<br />' . __('A backup of MySQL database before using this tool is highly recommended. The regenerate process of slugs might be not revertible!', 'permalink-manager'))
 
 
 
 
 
 
 
 
 
 
145
  ),
146
  );
147
-
148
  ?>
149
  <div id="permalinks-table-wrap" class="wrap">
150
-
151
  <?php
152
- // Display alerts and another content if needed
153
  echo apply_filters('permalink-manager-before-tabs','');
154
  ?>
155
-
156
  <div id="icon-themes" class="icon32"></div>
157
  <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>
158
-
159
  <h2 id="permalink-manager-tabs-nav" class="nav-tab-wrapper">
160
- <?php
161
  foreach($tabs as $tab_id => $tab_properties) {
162
  $active_class = ($active_tab === $tab_id) ? 'nav-tab-active nav-tab' : 'nav-tab';
163
  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>';
164
  } ?>
165
  </h2>
166
-
167
  <div id="permalink-manager-tabs">
168
  <?php
169
- foreach($tabs as $tab_id => $tab_properties) {
170
  $active_show = ($active_tab === $tab_id) ? 'show' : '';
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  echo '<div data-tab="' . $tab_id . '" id="' . $tab_id . '" class="' . $active_show . '">';
173
- echo (isset($tab_properties['description'])) ? "<div class=\"info alert\"><p>{$tab_properties['description']}</p></div>" : "";
174
- echo (isset($tab_properties['warning'])) ? "<div class=\"warning alert\"><p>{$tab_properties['warning']}</p></div>" : "";
175
  $this->$tab_properties['function']();
176
  echo '</div>';
177
  } ?>
178
  </div>
179
-
180
  <?php
181
- // Display alerts and another content if needed
182
  echo apply_filters('permalink-manager-after-tabs','');
183
  ?>
184
-
185
  </div>
186
  <?php
187
  }
@@ -199,7 +262,7 @@ class Permalink_Manager_Class {
199
  function enqueue_scripts() {
200
  wp_enqueue_script( PERMALINK_MANAGER_PLUGIN_NAME, PERMALINK_MANAGER_URL . '/js/permalink-manager-admin.js', array( 'jquery' ), PERMALINK_MANAGER_VERSION, false );
201
  }
202
-
203
  /**
204
  * Additional links on "Plugins" page
205
  */
@@ -207,159 +270,147 @@ class Permalink_Manager_Class {
207
  $links[] = '<a href="' . esc_url( get_admin_url(null, "tools.php?page=" . PERMALINK_MANAGER_OPTIONS_PAGE) ) .'">' . __( 'Go To Permalink Manager', 'permalink-manager' ) . '</a>';
208
  return $links;
209
  }
210
-
211
- /**
212
- * Fields for "Screen Options"
213
- */
214
- function fields_arrays($array) {
215
-
216
  // All registered post types array
217
- $all_post_types_array = Permalink_Manager_Helper_Functions::get_post_types_array();
218
  $all_post_statuses_array = get_post_statuses();
219
-
 
220
  // Fields for "Screen Options"
221
- $screen_options = array(
222
- 'post_types' => array(
223
- 'label' => __( 'Post Types', 'permalink-manager' ),
224
- 'type' => 'checkbox',
225
- 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types_array),
226
- 'default' => array('post', 'page')
227
- ),
228
  'post_statuses' => array(
229
  'label' => __( 'Post Statuses', 'permalink-manager' ),
230
- 'type' => 'checkbox',
231
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
232
  'default' => array('publish')
233
- ),
234
  'per_page' => array(
235
- 'label' => __( 'Per page', 'permalink-manager' ),
236
- 'type' => 'number',
237
- 'default' => 10
238
- )
239
- );
240
-
241
  // Fields for "Find and replace"
242
- $find_replace = array(
243
  'old_string' => array(
244
- 'label' => __( 'Find ...', 'permalink-manager' ),
245
- 'type' => 'text',
246
- ),
247
  'new_string' => array(
248
- 'label' => __( 'Replace with ...', 'permalink-manager' ),
249
- 'type' => 'text',
250
- ),
251
  'post_types' => array(
252
  'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
253
- 'type' => 'checkbox',
254
- 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types_array),
255
  'default' => array('post', 'page')
256
- ),
257
  'post_statuses' => array(
258
  'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
259
- 'type' => 'checkbox',
260
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
261
  'default' => array('publish')
262
- )
263
- );
264
-
265
  // Fields for "Regenerate slugs"
266
- $regenerate = array(
267
  'post_types' => array(
268
  'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
269
- 'type' => 'checkbox',
270
- 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types_array),
271
  'default' => array('post', 'page')
272
- ),
273
  'post_statuses' => array(
274
  'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
275
- 'type' => 'checkbox',
276
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
277
  'default' => array('publish')
278
- )
279
- );
280
-
281
  return isset($array) ? ${$array} : array();
282
- }
283
-
284
- /**
285
- * Check if the provided slug is unique and then update it with SQL query.
286
- */
287
- function update_slug_by_id($slug, $id) {
288
- global $wpdb;
289
-
290
- // Update slug and make it unique
291
- $slug = (empty($slug)) ? sanitize_title(get_the_title($id)) : $slug;
292
- $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
293
- $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
294
-
295
- return $new_slug;
296
- }
297
 
298
  /**
299
  * Bulk actions functions
300
  */
301
- function process_forms() {
302
  global $wpdb;
 
303
  $updated_slugs_count = 0;
304
  $updated_array = array();
305
  $alert_type = $alert_content = $errors = $main_content = '';
306
 
307
  if (isset($_POST['update_all_slugs'])) {
308
-
309
  $slugs = isset($_POST['slug']) ? $_POST['slug'] : array();
310
-
311
  // Double check if the slugs and ids are stored in arrays
312
  if (!is_array($slugs)) $slugs = explode(',', $slugs);
313
-
314
  if (!empty($slugs)) {
315
  foreach($slugs as $id => $new_slug) {
316
  $this_post = get_post($id);
317
-
318
- // Check if slug was changed
319
  if($this_post->post_name != $new_slug) {
320
  // Update slugs
321
- $this->update_slug_by_id($new_slug, $id);
322
-
323
  $updated_array[] = array('post_title' => get_the_title($id), 'old_slug' => $this_post->post_name, 'new_slug' => $new_slug);
324
  $updated_slugs_count++;
325
  }
326
-
327
  // Reset slug
328
  $slug = '';
329
  }
330
  }
331
-
332
  } else if (isset($_POST['find-replace-button'])) {
333
-
334
  $var['old_string'] = esc_sql($_POST['permalink-manager']['find-replace']['old_string']);
335
  $var['new_string'] = esc_sql($_POST['permalink-manager']['find-replace']['new_string']);
336
  $post_types_array = ($_POST['permalink-manager']['find-replace']['post_types']);
337
  $post_statuses_array = ($_POST['permalink-manager']['find-replace']['post_statuses']);
338
  $var['post_types'] = implode("', '", $post_types_array);
339
  $var['post_statuses'] = implode("', '", $post_statuses_array);
340
-
341
  // Check if any of variables is not empty
342
- $find_replace_fields = $this->fields_arrays('find_replace');
343
  foreach($var as $key => $val) {
344
- if(empty($val)) $errors .= '<p>' . sprintf( __( '<strong>"%1s"</strong> field is empty!', 'permalink-manager' ), $find_replace_fields[$key]['label'] ) . '</p>';
345
  }
346
-
347
  // Save the rows before they are updated to an array
348
  $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$var['post_statuses']}') AND post_name LIKE '%{$var['old_string']}%' AND post_type IN ('{$var['post_types']}')", ARRAY_A);
349
-
350
  // Now if the array is not empty use IDs from each subarray as a key
351
  if($posts_to_update && empty($errors)) {
352
  foreach ($posts_to_update as $row) {
353
  // Get new slug
354
  $old_slug = $row['post_name'];
355
  $new_slug = str_replace($var['old_string'], $var['new_string'], $old_slug);
356
-
357
  // Update slugs
358
- $this->update_slug_by_id($new_slug, $row['ID']);
359
-
360
  $updated_array[] = array('post_title' => $row['post_title'], 'old_slug' => $old_slug, 'new_slug' => $new_slug);
361
  $updated_slugs_count++;
362
-
363
  // Reset slug
364
  $slug = '';
365
  }
@@ -367,14 +418,13 @@ class Permalink_Manager_Class {
367
  $alert_type = 'error';
368
  $alert_content = $errors;
369
  }
370
-
371
-
372
  } else if (isset($_POST['regenerate-button'])) {
373
-
374
  // Setup needed variables
375
- $post_types_array = ($_POST['permalink-manager']['regenerate']['post_types']);
376
- $post_statuses_array = ($_POST['permalink-manager']['regenerate']['post_statuses']);
377
-
378
  // Reset query
379
  $reset_query = new WP_Query( array( 'post_type' => $post_types_array, 'post_status' => $post_statuses_array, 'posts_per_page' => -1 ) );
380
 
@@ -383,45 +433,54 @@ class Permalink_Manager_Class {
383
  while ( $reset_query->have_posts() ) {
384
  $reset_query->the_post();
385
  $this_post = get_post(get_the_ID());
386
-
387
  $correct_slug = sanitize_title(get_the_title());
388
  $old_slug = $this_post->post_name;
389
  $new_slug = wp_unique_post_slug($correct_slug, get_the_ID(), get_post_status(get_the_ID()), get_post_type(get_the_ID()), null);
390
-
391
  if($old_slug != $new_slug) {
392
  $updated_slugs_count++;
393
-
394
- $this->update_slug_by_id($new_slug, get_the_ID());
395
  $updated_array[] = array('post_title' => get_the_title(), 'old_slug' => $old_slug, 'new_slug' => $new_slug);
396
  }
397
  }
398
  }
399
-
400
  // Restore original Post Data
401
  wp_reset_postdata();
402
-
 
 
 
 
 
 
 
 
 
 
 
 
403
  }
404
-
405
  /**
406
  * Display results
407
  */
408
  if((isset($_POST['permalink-manager']) || isset($_POST['update_all_slugs'])) && !(isset($_POST['screen-options-apply']))) {
409
  // Display errors or success message
410
- add_filter('permalink-manager-before-tabs', function( $arg ) use ( $updated_slugs_count, $alert_content, $alert_type ) {
411
-
412
- // Check how many rows/slugs were affected
413
- 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
- return Permalink_Manager_Helper_Functions::display_alert($alert_content, $alert_type);
 
 
 
 
 
 
 
 
423
 
424
- });
425
 
426
  // Display summary after update
427
  // Display only if there are any slugs updated
@@ -457,8 +516,111 @@ class Permalink_Manager_Class {
457
 
458
  });
459
  }
460
- }
461
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
 
464
  /**
@@ -468,14 +630,13 @@ function run_permalink_manager() {
468
 
469
  // Load plugin files.
470
  if( is_admin() ) {
471
-
472
- require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-wp-table.php';
473
  require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-screen-options.php';
474
  require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-helper-functions.php';
475
-
476
  $Permalink_Manager_Class = new Permalink_Manager_Class();
477
  $Permalink_Manager_Screen_Options = new Permalink_Manager_Screen_Options();
478
-
479
  }
480
 
481
  }
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.3.0
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
20
 
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'permalink-manager' );
23
+ define( 'PERMALINK_MANAGER_VERSION', '0.3.0' );
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' );
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
+
38
  add_action( 'plugins_loaded', array($this, 'localize_me') );
39
+ add_action( 'init', array($this, 'flush_rewrite_rules') );
40
+ add_action( 'admin_init', array($this, 'bulk_actions') );
41
  add_action( 'admin_menu', array($this, 'add_menu_page') );
42
  add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugins_page_links') );
43
+
44
+ add_filter( 'rewrite_rules_array', array($this, 'custom_permalinks_rewrite_rules'), 999, 1);
45
+ add_filter( '_get_page_link', array($this, 'custom_permalinks'), 999, 2);
46
+ add_filter( 'post_link', array($this, 'custom_permalinks'), 999, 2);
47
+ add_filter( 'post_type_link', array($this, 'custom_permalinks'), 999, 2);
48
+
49
  }
50
+
51
  /**
52
  * Localize this plugin
53
  */
54
  function localize_me() {
55
  load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
56
  }
57
+
58
  /**
59
  * Add menu page and load CSS & JS.
60
  */
61
  function add_menu_page() {
62
  add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', PERMALINK_MANAGER_OPTIONS_PAGE, array($this, 'list_slugs_admin_page') );
63
+
64
  // Make sure thata the CSS and JS files are loaded only on plugin admin page.
65
  add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_styles' ) );
66
  add_action( 'admin_print_scripts-' . PERMALINK_MANAGER_MENU_PAGE, array($this, 'enqueue_scripts' ) );
67
  }
68
+
69
  /**
70
  * Display the table with slugs.
71
  */
72
+ function slug_editor_html() {
73
  global $wpdb;
74
+
75
+ $Permalink_Manager_Slug_Editor = new Permalink_Manager_Slug_Editor();
76
+ $Permalink_Manager_Slug_Editor->set_screen_option_fields($this->fields_arrays('screen_options'));
77
+ $Permalink_Manager_Slug_Editor->prepare_items($wpdb->posts);
78
+
79
  ?>
80
+
81
  <form id="permalinks-table" method="post">
82
+ <input type="hidden" name="tab" value="slug_editor" />
83
+ <?php echo $Permalink_Manager_Slug_Editor->display(); ?>
84
  </form>
85
  <?php
86
  }
87
+
88
  /**
89
  * Mass replace options page.
90
  */
91
  function find_and_replace_html() {
92
  $button = get_submit_button( __( 'Find & Replace', 'permalink-manager' ), 'primary', 'find-replace-button', false );
93
+
94
  $return = "<form id=\"permalinks-table-find-replace\" method=\"post\">";
95
+ $return .= "<input type=\"hidden\" name=\"tab\" value=\"find_and_replace\" />";
96
+ $return .= "<table class=\"form-table\">";
97
+
98
+ foreach($this->fields_arrays('find_and_replace') as $field_name => $field_args) {
99
+ $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'find-replace');
100
+ }
101
+
102
+ $return .= "</table>{$button}";
103
  $return .= "</form>";
104
+
105
  echo $return;
106
  }
107
+
108
  /**
109
  * Reset slugs page.
110
  */
111
+ function regenerate_slugs_html() {
112
  $button = get_submit_button( __( 'Regenerate', 'permalink-manager' ), 'primary', 'regenerate-button', false );
113
+
114
  $return = "<form id=\"permalinks-table-regenerate\" method=\"post\">";
115
+ $return .= "<input type=\"hidden\" name=\"tab\" value=\"regenerate_slugs\" />";
116
  $return .= "<table class=\"form-table\">";
117
+
118
+ foreach($this->fields_arrays('regenerate_slugs') as $field_name => $field_args) {
119
+ $return .= Permalink_Manager_Helper_Functions::generate_option_field($field_name, $field_args, 'regenerate_slugs');
120
  }
121
+
122
  $return .= "</table>{$button}";
123
  $return .= "</form>";
124
+
125
  echo $return;
126
  }
127
+
128
+ /**
129
+ * Permalink Base Editor
130
+ */
131
+ function base_editor_html() {
132
+ global $wpdb, $wp_rewrite;
133
+
134
+ $Permalink_Manager_Base_Editor = new Permalink_Manager_Base_Editor();
135
+ $Permalink_Manager_Base_Editor->set_screen_option_fields($this->fields_arrays('screen_options'));
136
+ $Permalink_Manager_Base_Editor->prepare_items($wpdb->posts);
137
+
138
+ //echo '<pre>';
139
+ //print_r($wp_rewrite);
140
+ //echo '</pre>';
141
+
142
+ ?>
143
+
144
+ <form id="permalinks-base-table" method="post">
145
+ <input type="hidden" name="tab" value="base_editor" />
146
+ <?php echo $Permalink_Manager_Base_Editor->display(); ?>
147
+ </form>
148
+ <?php
149
+ }
150
+
151
  /**
152
  * Display the plugin dashboard.
153
  */
154
  function list_slugs_admin_page() {
155
  global $wpdb;
156
+
157
  // Check which tab is active now.
158
+ if(isset($_POST['tab'])) {
159
+ $active_tab = $_POST['tab'];
160
+ } else if(isset($_GET['tab'])) {
161
+ $active_tab = $_GET['tab'];
162
+ } else {
163
+ $active_tab = 'slug_editor';
164
+ }
165
+
166
  // Tabs array with assigned functions used to display HTML content.
167
  $tabs = array(
168
+ 'slug_editor' => array(
169
+ 'name' => __('Slug Editor', 'permalink-manager'),
170
+ 'function' => 'slug_editor_html',
171
+ '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')
172
  ),
173
  'find_and_replace' => array(
174
+ 'name' => __('Find and replace', 'permalink-manager'),
175
  'function' => 'find_and_replace_html',
176
+ 'warning' => (__('<strong>You are doing it at your own risk!</strong>', 'permalink-manager') . '<br />' . __('A backup of MySQL database before using this tool is highly recommended. The search & replace operation might be not revertible!', 'permalink-manager'))
177
  ),
178
  'regenerate_slugs' => array(
179
+ 'name' => __('Regenerate slugs', 'permalink-manager'),
180
  'function' => 'regenerate_slugs_html',
181
+ 'warning' => (__('<strong>You are doing it at your own risk!</strong>', 'permalink-manager') . '<br />' . __('A backup of MySQL database before using this tool is highly recommended. The regenerate process of slugs might be not revertible!', 'permalink-manager'))
182
+ ),
183
+ 'base_editor' => array(
184
+ 'name' => __('Permalinks Base Editor', 'permalink-manager'),
185
+ 'function' => 'base_editor_html',
186
+ 'warning' => array(
187
+ 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'),
188
+ __('Custom Post Types should have their own, unique front, eg. <em>products/%product%!</em>', 'permalink-manager'),
189
+ __('After you update & save the settings below, you need to flush the rewrite rules!', 'permalink-manager'),
190
+ ),
191
+ '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())
192
  ),
193
  );
194
+
195
  ?>
196
  <div id="permalinks-table-wrap" class="wrap">
197
+
198
  <?php
199
+ // Display alerts and another content if needed
200
  echo apply_filters('permalink-manager-before-tabs','');
201
  ?>
202
+
203
  <div id="icon-themes" class="icon32"></div>
204
  <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>
205
+
206
  <h2 id="permalink-manager-tabs-nav" class="nav-tab-wrapper">
207
+ <?php
208
  foreach($tabs as $tab_id => $tab_properties) {
209
  $active_class = ($active_tab === $tab_id) ? 'nav-tab-active nav-tab' : 'nav-tab';
210
  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>';
211
  } ?>
212
  </h2>
213
+
214
  <div id="permalink-manager-tabs">
215
  <?php
216
+ foreach($tabs as $tab_id => $tab_properties) {
217
  $active_show = ($active_tab === $tab_id) ? 'show' : '';
218
 
219
+ // Prepare warning & description texts
220
+ $warning = (isset($tab_properties['warning'])) ? $tab_properties['warning'] : '';
221
+ $description = (isset($tab_properties['description'])) ? $tab_properties['description'] : '';
222
+
223
+ if(is_array($warning)) {
224
+ $warning = "<ol>"; // Overwrite the variable
225
+ foreach($tab_properties['warning'] as $point) { $warning .= "<li>{$point}</li>"; }
226
+ $warning .= "</ol>";
227
+ }
228
+
229
+ if(is_array($description)) {
230
+ $description = "<ol>"; // Overwrite the variable
231
+ foreach($tab_properties['description'] as $point) { $description .= "<li>{$point}</li>"; }
232
+ $description .= "</ol>";
233
+ }
234
+
235
  echo '<div data-tab="' . $tab_id . '" id="' . $tab_id . '" class="' . $active_show . '">';
236
+ echo ($warning) ? "<div class=\"warning alert\">" . wpautop($warning) . "</div>" : "";
237
+ echo (isset($tab_properties['description'])) ? "<div class=\"info alert\">" . wpautop($description) . "</div>" : "";
238
  $this->$tab_properties['function']();
239
  echo '</div>';
240
  } ?>
241
  </div>
242
+
243
  <?php
244
+ // Display alerts and another content if needed
245
  echo apply_filters('permalink-manager-after-tabs','');
246
  ?>
247
+
248
  </div>
249
  <?php
250
  }
262
  function enqueue_scripts() {
263
  wp_enqueue_script( PERMALINK_MANAGER_PLUGIN_NAME, PERMALINK_MANAGER_URL . '/js/permalink-manager-admin.js', array( 'jquery' ), PERMALINK_MANAGER_VERSION, false );
264
  }
265
+
266
  /**
267
  * Additional links on "Plugins" page
268
  */
270
  $links[] = '<a href="' . esc_url( get_admin_url(null, "tools.php?page=" . PERMALINK_MANAGER_OPTIONS_PAGE) ) .'">' . __( 'Go To Permalink Manager', 'permalink-manager' ) . '</a>';
271
  return $links;
272
  }
273
+
274
+ /**
275
+ * Fields for "Screen Options"
276
+ */
277
+ function fields_arrays($array) {
278
+
279
  // All registered post types array
 
280
  $all_post_statuses_array = get_post_statuses();
281
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
282
+
283
  // Fields for "Screen Options"
284
+ $screen_options = array(
285
+ 'post_types' => array(
286
+ 'label' => __( 'Post Types', 'permalink-manager' ),
287
+ 'type' => 'checkbox',
288
+ 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
289
+ 'default' => array('post', 'page')
290
+ ),
291
  'post_statuses' => array(
292
  'label' => __( 'Post Statuses', 'permalink-manager' ),
293
+ 'type' => 'checkbox',
294
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
295
  'default' => array('publish')
296
+ ),
297
  'per_page' => array(
298
+ 'label' => __( 'Per page', 'permalink-manager' ),
299
+ 'type' => 'number',
300
+ 'default' => 10
301
+ )
302
+ );
303
+
304
  // Fields for "Find and replace"
305
+ $find_and_replace = array(
306
  'old_string' => array(
307
+ 'label' => __( 'Find ...', 'permalink-manager' ),
308
+ 'type' => 'text',
309
+ ),
310
  'new_string' => array(
311
+ 'label' => __( 'Replace with ...', 'permalink-manager' ),
312
+ 'type' => 'text',
313
+ ),
314
  'post_types' => array(
315
  'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
316
+ 'type' => 'checkbox',
317
+ 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
318
  'default' => array('post', 'page')
319
+ ),
320
  'post_statuses' => array(
321
  'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
322
+ 'type' => 'checkbox',
323
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
324
  'default' => array('publish')
325
+ )
326
+ );
327
+
328
  // Fields for "Regenerate slugs"
329
+ $regenerate_slugs = array(
330
  'post_types' => array(
331
  'label' => __( 'Post Types that should be affected', 'permalink-manager' ),
332
+ 'type' => 'checkbox',
333
+ 'choices' => array_merge(array('all' => '<strong>' . __('All Post Types', 'permalink-manager') . '</strong>'), $all_post_types),
334
  'default' => array('post', 'page')
335
+ ),
336
  'post_statuses' => array(
337
  'label' => __( 'Post Statuses that should be affected', 'permalink-manager' ),
338
+ 'type' => 'checkbox',
339
  'choices' => array_merge(array('all' => '<strong>' . __('All Post Statuses', 'permalink-manager') . '</strong>'), $all_post_statuses_array),
340
  'default' => array('publish')
341
+ )
342
+ );
343
+
344
  return isset($array) ? ${$array} : array();
345
+
346
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
347
 
348
  /**
349
  * Bulk actions functions
350
  */
351
+ function bulk_actions() {
352
  global $wpdb;
353
+
354
  $updated_slugs_count = 0;
355
  $updated_array = array();
356
  $alert_type = $alert_content = $errors = $main_content = '';
357
 
358
  if (isset($_POST['update_all_slugs'])) {
359
+
360
  $slugs = isset($_POST['slug']) ? $_POST['slug'] : array();
361
+
362
  // Double check if the slugs and ids are stored in arrays
363
  if (!is_array($slugs)) $slugs = explode(',', $slugs);
364
+
365
  if (!empty($slugs)) {
366
  foreach($slugs as $id => $new_slug) {
367
  $this_post = get_post($id);
368
+
369
+ // Check if slug was changed
370
  if($this_post->post_name != $new_slug) {
371
  // Update slugs
372
+ Permalink_Manager_Helper_Functions::update_slug_by_id($new_slug, $id);
373
+
374
  $updated_array[] = array('post_title' => get_the_title($id), 'old_slug' => $this_post->post_name, 'new_slug' => $new_slug);
375
  $updated_slugs_count++;
376
  }
377
+
378
  // Reset slug
379
  $slug = '';
380
  }
381
  }
382
+
383
  } else if (isset($_POST['find-replace-button'])) {
384
+
385
  $var['old_string'] = esc_sql($_POST['permalink-manager']['find-replace']['old_string']);
386
  $var['new_string'] = esc_sql($_POST['permalink-manager']['find-replace']['new_string']);
387
  $post_types_array = ($_POST['permalink-manager']['find-replace']['post_types']);
388
  $post_statuses_array = ($_POST['permalink-manager']['find-replace']['post_statuses']);
389
  $var['post_types'] = implode("', '", $post_types_array);
390
  $var['post_statuses'] = implode("', '", $post_statuses_array);
391
+
392
  // Check if any of variables is not empty
393
+ $find_and_replace_fields = $this->fields_arrays('find_and_replace');
394
  foreach($var as $key => $val) {
395
+ if(empty($val)) $errors .= '<p>' . sprintf( __( '<strong>"%1s"</strong> field is empty!', 'permalink-manager' ), $find_and_replace_fields[$key]['label'] ) . '</p>';
396
  }
397
+
398
  // Save the rows before they are updated to an array
399
  $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$var['post_statuses']}') AND post_name LIKE '%{$var['old_string']}%' AND post_type IN ('{$var['post_types']}')", ARRAY_A);
400
+
401
  // Now if the array is not empty use IDs from each subarray as a key
402
  if($posts_to_update && empty($errors)) {
403
  foreach ($posts_to_update as $row) {
404
  // Get new slug
405
  $old_slug = $row['post_name'];
406
  $new_slug = str_replace($var['old_string'], $var['new_string'], $old_slug);
407
+
408
  // Update slugs
409
+ Permalink_Manager_Helper_Functions::update_slug_by_id($new_slug, $row['ID']);
410
+
411
  $updated_array[] = array('post_title' => $row['post_title'], 'old_slug' => $old_slug, 'new_slug' => $new_slug);
412
  $updated_slugs_count++;
413
+
414
  // Reset slug
415
  $slug = '';
416
  }
418
  $alert_type = 'error';
419
  $alert_content = $errors;
420
  }
421
+
 
422
  } else if (isset($_POST['regenerate-button'])) {
423
+
424
  // Setup needed variables
425
+ $post_types_array = ($_POST['permalink-manager']['regenerate_slugs']['post_types']);
426
+ $post_statuses_array = ($_POST['permalink-manager']['regenerate_slugs']['post_statuses']);
427
+
428
  // Reset query
429
  $reset_query = new WP_Query( array( 'post_type' => $post_types_array, 'post_status' => $post_statuses_array, 'posts_per_page' => -1 ) );
430
 
433
  while ( $reset_query->have_posts() ) {
434
  $reset_query->the_post();
435
  $this_post = get_post(get_the_ID());
436
+
437
  $correct_slug = sanitize_title(get_the_title());
438
  $old_slug = $this_post->post_name;
439
  $new_slug = wp_unique_post_slug($correct_slug, get_the_ID(), get_post_status(get_the_ID()), get_post_type(get_the_ID()), null);
440
+
441
  if($old_slug != $new_slug) {
442
  $updated_slugs_count++;
443
+
444
+ Permalink_Manager_Helper_Functions::update_slug_by_id($new_slug, get_the_ID());
445
  $updated_array[] = array('post_title' => get_the_title(), 'old_slug' => $old_slug, 'new_slug' => $new_slug);
446
  }
447
  }
448
  }
449
+
450
  // Restore original Post Data
451
  wp_reset_postdata();
452
+
453
+ // Save Permalink Structures/Permalinks Bases
454
+ } else if (isset($_POST['save_permalink_structures'])) {
455
+ Permalink_Manager_Helper_Functions::save_option('base-editor', $_POST['permalink-manager']['base-editor']);
456
+
457
+ $alert_type = 'updated';
458
+ $alert_content = sprintf( __( '<a href="%s">Click here</a> to flush the rewrite rules (it is required to make the new permalinks working).', 'permalink-manager' ), admin_url('admin.php?page=' . PERMALINK_MANAGER_PLUGIN_NAME . '.php&flush_rewrite_rules=true&tab=base_editor'));
459
+ Permalink_Manager_Helper_Functions::display_alert($alert_content, $alert_type, true);
460
+ return;
461
+ // Flush rewrite rules
462
+ } else if (isset($_POST['flush_rewrite_rules'])) {
463
+ $this->flush_rewrite_rules();
464
+ return;
465
  }
466
+
467
  /**
468
  * Display results
469
  */
470
  if((isset($_POST['permalink-manager']) || isset($_POST['update_all_slugs'])) && !(isset($_POST['screen-options-apply']))) {
471
  // Display errors or success message
 
 
 
 
 
 
 
 
 
 
 
472
 
473
+ // Check how many rows/slugs were affected
474
+ if($updated_slugs_count > 0) {
475
+ $alert_type = 'updated';
476
+ $alert_content = sprintf( _n( '<strong>%d</strong> slug were updated!', '<strong>%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
477
+ $alert_content .= sprintf( __( '<a href="%s">Click here</a> to go to the list of updated slugs', 'permalink-manager' ), '#updated-list');
478
+ } else {
479
+ $alert_type = 'error';
480
+ $alert_content = ($alert_content) ? $alert_content : __( '<strong>No slugs</strong> were updated!', 'permalink-manager' );
481
+ }
482
 
483
+ Permalink_Manager_Helper_Functions::display_alert($alert_content, $alert_type, true);
484
 
485
  // Display summary after update
486
  // Display only if there are any slugs updated
516
 
517
  });
518
  }
519
+ }
520
+ }
521
+
522
+ /**
523
+ * Change permalinks for posts, pages & custom post types
524
+ */
525
+ function custom_permalinks($permalink, $post) {
526
+ $post = (is_integer($post)) ? get_post($post) : $post;
527
+ $post_type = $post->post_type;
528
+ $permastruct = isset($this->permalink_manager_options['base-editor'][$post_type]) ? $this->permalink_manager_options['base-editor'][$post_type] : '';
529
+
530
+ // Ignore empty permastructures (do not change them)
531
+ if(empty($permastruct) || $post->post_status != 'publish') return $permalink;
532
+
533
+ // Get options
534
+ if($permastruct) {
535
+ $permalink = home_url() . "/" . trim($permastruct, '/');
536
+ }
537
+
538
+ /**
539
+ * Replace Structure Tags
540
+ */
541
+
542
+ // Get the date
543
+ $date = explode(" ",date('Y m d H i s', strtotime($post->post_date)));
544
+
545
+ // Get the category (if needed)
546
+ $category = '';
547
+ if ( strpos($permalink, '%category%') !== false ) {
548
+ $cats = get_the_category($post->ID);
549
+ if ( $cats ) {
550
+ usort($cats, '_usort_terms_by_ID'); // order by ID
551
+ $category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
552
+ $category_object = get_term( $category_object, 'category' );
553
+ $category = $category_object->slug;
554
+ if ( $parent = $category_object->parent )
555
+ $category = get_category_parents($parent, false, '/', true) . $category;
556
+ }
557
+ // show default category in permalinks, without having to assign it explicitly
558
+ if ( empty($category) ) {
559
+ $default_category = get_term( get_option( 'default_category' ), 'category' );
560
+ $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
561
+ }
562
+ }
563
+
564
+ // Get the author (if needed)
565
+ $author = '';
566
+ if ( strpos($permalink, '%author%') !== false ) {
567
+ $authordata = get_userdata($post->post_author);
568
+ $author = $authordata->user_nicename;
569
+ }
570
+
571
+ // Fix for hierarchical CPT (start)
572
+ $full_slug = get_page_uri($post);
573
+ $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
574
+
575
+ // Do the replacement (post tag is removed now to enable support for hierarchical CPT)
576
+ $tags = array('%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', '%post_id%', '%category%', '%author%', $post_type_tag);
577
+ $replacements = array($date[0], $date[1], $date[2], $date[3], $date[4], $date[5], $post->ID, $category, $author, '');
578
+
579
+ return str_replace($tags, $replacements, "{$permalink}{$full_slug}");
580
+ }
581
+
582
+ /**
583
+ * Add rewrite rules
584
+ */
585
+ function custom_permalinks_rewrite_rules($rules) {
586
+
587
+ global $wp_rewrite;
588
+
589
+ $new_rules = array();
590
+ $permastructures = $this->permalink_manager_options['base-editor'];
591
+
592
+ // Move post & page permastructures to the end of array
593
+ $page_p = $permastructures['page'];
594
+ $post_p = $permastructures['post'];
595
+ unset($permastructures['post'], $permastructures['page']);
596
+
597
+ $permastructures['page'] = $page_p;
598
+ $permastructures['post'] = $post_p;
599
+ $permastructures = array_reverse($permastructures);
600
+
601
+ foreach($permastructures as $post_type => $permastruct) {
602
+ // Ignore empty permastructures (do not add them)
603
+ if(empty($permastruct)) continue;
604
+
605
+ $new_rule = $wp_rewrite->generate_rewrite_rules($wp_rewrite->root . $permastruct, EP_PERMALINK);
606
+ $rules = array_merge($new_rule, $rules);
607
+ }
608
+ return $rules;
609
+ }
610
+
611
+ /**
612
+ * Flush rewrite rules
613
+ */
614
+ function flush_rewrite_rules() {
615
+ if(isset($_REQUEST['flush_rewrite_rules'])) {
616
+ flush_rewrite_rules();
617
+
618
+ $alert_type = 'updated';
619
+ $alert_content = __( 'The rewrite rules are flushed!', 'permalink-manager' );
620
+ return Permalink_Manager_Helper_Functions::display_alert($alert_content, $alert_type, true);
621
+ }
622
+ }
623
+
624
  }
625
 
626
  /**
630
 
631
  // Load plugin files.
632
  if( is_admin() ) {
633
+ require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-slug-editor.php';
634
+ require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-base-editor.php';
635
  require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-screen-options.php';
636
  require_once PERMALINK_MANAGER_DIR . '/inc/permalink-manager-helper-functions.php';
637
+
638
  $Permalink_Manager_Class = new Permalink_Manager_Class();
639
  $Permalink_Manager_Screen_Options = new Permalink_Manager_Screen_Options();
 
640
  }
641
 
642
  }