Permalink Manager Lite - Version 0.5.4

Version Description

  • Additional hook for custom slug
Download this release

Release Info

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

Code changes from version 0.4.9 to 0.5.4

README.txt CHANGED
@@ -4,54 +4,50 @@ License: GPLv3
4
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
5
  Tags: urls, permalinks, slugs, custom url, custom permalinks, uris, url, slug, permalink
6
  Requires at least: 4.0
7
- Tested up to: 4.6.1
8
- Stable tag: 0.4.9
9
 
10
- Permalink Manager allows you to control how the permalinks for custom post types are created & regenerate them.
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
 
18
- 1. You can manually adjust the URIs & slugs of all posts/pages/custom post type items.
19
- 2. You can replace particular (sub)string that is a part of slug and/or URI with another (sub)string.
20
- 3. You can regenerate/reset the slugs and/or URIs 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`):
26
 
27
- `http://example.com/krakow/hotels-in-krakow
28
- http://example.com/krakow/restaurants-in-krakow
29
- http://example.com/krakow/transport-in-krakow
30
- http://example.com/blog/krakow-the-best-city-for-tourists
31
- http://example.com/poland/cities/krakow
32
- http://example.com/poland/cities/stalowa-wola
33
- http://example.com/poland/cities/warszawa
34
- http://example.com/poland/cities/poznan`
35
 
36
- If you use the form from `Find and replace` section your URLs will be changed to:
 
 
 
 
 
 
 
37
 
38
- `http://example.com/gdansk/hotels-in-gdansk
39
- http://example.com/gdansk/restaurants-in-gdansk
40
- http://example.com/gdansk/transport-in-gdansk
41
- http://example.com/blog/gdansk-the-best-city-for-tourists
42
- http://example.com/poland/cities/gdansk
43
- http://example.com/poland/cities/stalowa-wola
44
- http://example.com/poland/cities/warszawa
45
- http://example.com/poland/cities/poznan`
46
 
47
- = Upcoming features =
 
 
 
 
 
48
 
49
- In the next version of plugin more functionalities will be added:
50
 
51
- * Support for taxonomies
52
  * REGEX for `Find and replace` section
53
- * Support for WPML
54
- * Two-step updater, so you can double-check which permalinks will be changed before the change is applied
55
  * AJAX support.
56
 
57
  == Installation ==
@@ -68,12 +64,14 @@ After the plugin is installed you can access its dashboard from this page: `Tool
68
 
69
  == Screenshots ==
70
 
71
- 1. Main dashboard.
72
- 2. Find and replace section.
73
- 3. Regenerate section.
74
- 4. Custom permastructures.
75
  5. A list of updated posts.
76
  6. Editable URI box in Post/Page/CPT edit pagees.
 
 
77
 
78
  == Frequently Asked Questions ==
79
 
@@ -82,6 +80,20 @@ After the plugin is installed you can access its dashboard from this page: `Tool
82
 
83
  == Changelog ==
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  = 0.4.9 =
86
  * Hook for removed posts (their URI is now automatically removed)
87
 
4
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
5
  Tags: urls, permalinks, slugs, custom url, custom permalinks, uris, url, slug, permalink
6
  Requires at least: 4.0
7
+ Tested up to: 4.7.2
8
+ Stable tag: 0.5.4
9
 
10
+ Permalink Manager helps to maintain and bulk regenerate or "find and replace" any word in your permalinks & slugs.
11
 
12
  == Description ==
13
 
14
+ A really intuitive and easy-to-use plugin that helps to manage the permalinks for all your posts, pages and other custom post types items.
15
 
16
+ Currently, the plugin allows to perform four main actions:
17
 
18
+ 1. It allows to manually adjust selected permalinks (URIs or native slugs) for all posts/pages/custom post type items.
19
+ 2. It allows to bulk replace particular words used in permalinks (or native slugs) with another words (works also with substring).
20
+ 3. It allows to bulk regenerate/reset permalinks (or native slugs). This might be especially useful if your post titles are updated and native slugs need to be recreated.
21
+ 4. It allows to change the default permalink bases (permastructures) for all custom post types & posts and pages.
22
 
23
+ To improve the user experience, each tool allows also to filter the permalinks by post types or post statuses.
24
 
25
+ = "Find and replace" usage example =
26
 
27
+ Word "krakow" should be replaced with "gdansk" in all your permalinks.
 
 
 
 
 
 
 
28
 
29
+ `http://example.com/krakow/hotels-in-krakow === [changed] ===> http://example.com/gdansk/hotels-in-gdansk
30
+ http://example.com/krakow/restaurants-in-krakow === [changed] ===> http://example.com/gdansk/restaurants-in-gdansk
31
+ http://example.com/krakow/transport-in-krakow === [changed] ===> http://example.com/gdansk/transport-in-gdansk
32
+ http://example.com/blog/krakow-the-best-city-for-tourists === [changed] ===> http://example.com/blog/gdansk-the-best-city-for-tourists
33
+ http://example.com/poland/cities/krakow === [changed] ===> http://example.com/poland/cities/gdansk
34
+ http://example.com/poland/cities/stalowa-wola === [not changed] ===> http://example.com/cities/stalowa-wola
35
+ http://example.com/poland/cities/warszawa === [not changed] ===> http://example.com/poland/cities/warszawa
36
+ http://example.com/poland/cities/poznan === [not changed] ===> http://example.com/poland/cities/poznan`
37
 
38
+ = All features =
 
 
 
 
 
 
 
39
 
40
+ * "Permalink Editor" - list of your permalinks (groupped by post types).
41
+ * "Regenerate/Reset" permalinks, custom and native URIs (slugs).
42
+ * "Find and replace" strings in permalinks, custom and native URIs (slugs).
43
+ * Support for "Primary Term" functionality implemented in "Yoast SEO" plugin.
44
+ * Optional redirect (301 or 302) from old (native) permalinks to new (custom) permalinks.
45
+ * Possibility to disable native canonical redirects.
46
 
47
+ = Planned functionalities =
48
 
 
49
  * REGEX for `Find and replace` section
50
+ * Support for WPML and another language plugins
 
51
  * AJAX support.
52
 
53
  == Installation ==
64
 
65
  == Screenshots ==
66
 
67
+ 1. "Permalink editor".
68
+ 2. "Find and replace" section.
69
+ 3. "Regenerate/Reset" section.
70
+ 4. "Permastructures" section.
71
  5. A list of updated posts.
72
  6. Editable URI box in Post/Page/CPT edit pagees.
73
+ 7. Settings section.
74
+ 8. Developer section.
75
 
76
  == Frequently Asked Questions ==
77
 
80
 
81
  == Changelog ==
82
 
83
+ = 0.5.4 =
84
+ * Additional hook for custom slug
85
+
86
+ = 0.5.2/0.5.3 =
87
+ * Another hotfix
88
+
89
+ = 0.5.1 =
90
+ * Hotfix for "Settings" section
91
+
92
+ = 0.5.0 =
93
+ * Code refactoring completed
94
+ * Interface changes
95
+ * Hooks enabled
96
+
97
  = 0.4.9 =
98
  * Hook for removed posts (their URI is now automatically removed)
99
 
inc/permalink-manager-actions.php DELETED
@@ -1,230 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Additional functions used in classes and another subclasses
5
- */
6
-
7
- class Permalink_Manager_Actions extends Permalink_Manager_Class {
8
-
9
- public function __construct() {}
10
-
11
- /**
12
- * Find & replace (bulk action)
13
- */
14
- static function find_replace($find_and_replace_fields) {
15
- global $wpdb;
16
-
17
- // Reset variables
18
- $updated_slugs_count = 0;
19
- $updated_array = array();
20
- $alert_type = $alert_content = $errors = $main_content = '';
21
- $old_uris = get_option('permalink-manager-uris', array());
22
-
23
- // Prepare default variables from $_POST object
24
- $old_string = esc_sql($_POST['permalink-manager']['find-replace']['old_string']);
25
- $new_string = esc_sql($_POST['permalink-manager']['find-replace']['new_string']);
26
- $mode = isset($_POST['permalink-manager']['find-replace']['variant']) ? $_POST['permalink-manager']['find-replace']['variant'] : array('slugs');
27
- $post_types_array = ($_POST['permalink-manager']['find-replace']['post_types']);
28
- $post_statuses_array = ($_POST['permalink-manager']['find-replace']['post_statuses']);
29
- $post_types = implode("', '", $post_types_array);
30
- $post_statuses = implode("', '", $post_statuses_array);
31
-
32
- // Save the rows before they are updated to an array
33
- //$posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_name LIKE '%{$old_string}%' AND post_type IN ('{$post_types}')", ARRAY_A);
34
- $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
35
-
36
- // Now if the array is not empty use IDs from each subarray as a key
37
- if($posts_to_update && empty($errors)) {
38
- foreach ($posts_to_update as $row) {
39
-
40
- // Prepare variables
41
- $old_post_name = $row['post_name'];
42
- $old_default_uri = trim(str_replace(home_url("/"), "", get_permalink($row['ID'])), "/");
43
- $new_default_uri = Permalink_Manager_Helper_Functions::get_uri($row['ID'], true);
44
- $old_uri = (isset($old_uris[$row['ID']])) ? $old_uris[$row['ID']] : $new_default_uri;
45
- $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
46
- $old_base = (strpos($old_uri, '/') !== false) ? substr($old_uri, 0, strrpos( $old_uri, '/') ) : '';
47
-
48
- // Process URI & slug
49
- $new_slug = str_replace($old_string, $new_string, $old_slug);
50
- $new_base = str_replace($old_string, $new_string, $old_base);
51
- $new_uri = (in_array('both', $mode)) ? trim("{$new_base}/{$new_slug}", "/") : trim("{$old_base}/{$new_slug}", "/");
52
- $new_post_name = (in_array('post_names', $mode)) ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
53
-
54
- // Check if native slug should be changed
55
- if(in_array('post_names', $mode) && ($old_post_name != $new_post_name)) {
56
- Permalink_Manager_Helper_Functions::update_slug_by_id($new_post_name, $row['ID']);
57
- }
58
-
59
- if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
60
- $old_uris[$row['ID']] = $new_uri;
61
- $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
62
- $updated_slugs_count++;
63
- }
64
- }
65
-
66
- // Filter array before saving
67
- $old_uris = array_filter($old_uris);
68
- update_option('permalink-manager-uris', $old_uris);
69
-
70
- $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
71
- wp_reset_postdata();
72
- }
73
-
74
- return ($output) ? $output : "";
75
- }
76
-
77
- /**
78
- * Regenerate slugs & bases (bulk action)
79
- */
80
- static function regenerate_all_permalinks() {
81
- // Setup needed variables
82
- $updated_slugs_count = 0;
83
- $updated_array = array();
84
- $alert_type = $alert_content = $errors = $main_content = '';
85
-
86
- $post_types_array = ($_POST['permalink-manager']['regenerate_slugs']['post_types']);
87
- $post_statuses_array = ($_POST['permalink-manager']['regenerate_slugs']['post_statuses']);
88
- $mode = isset($_POST['permalink-manager']['regenerate_slugs']['variant']) ? $_POST['permalink-manager']['regenerate_slugs']['variant'] : array('slugs');
89
-
90
- $old_uris = get_option('permalink-manager-uris', array());
91
- $all_permastructs = get_option('permalink-manager-permastructs', array());
92
-
93
- // Reset query
94
- $reset_query = new WP_Query( array( 'post_type' => $post_types_array, 'post_status' => $post_statuses_array, 'posts_per_page' => -1 ) );
95
-
96
- // The Loop
97
- if ( $reset_query->have_posts() ) {
98
- while ( $reset_query->have_posts() ) {
99
- $reset_query->the_post();
100
- $post_id = get_the_ID();
101
- $this_post = get_post($post_id);
102
- $updated = 0;
103
-
104
- // Prepare permastructs
105
- $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($this_post->post_type);
106
- $custom_permastruct = isset($all_permastructs[$this_post->post_type]) ? $all_permastructs[$this_post->post_type] : $default_permastruct;
107
-
108
- // Prepare variables
109
- $old_post_name = $this_post->post_name;
110
- $old_default_uri = trim(str_replace(home_url("/"), "", get_permalink($post_id)), "/");
111
- $new_default_uri = Permalink_Manager_Helper_Functions::get_uri($post_id, true);
112
- $old_uri = isset($old_uris[$post_id]) ? trim($old_uris[$post_id], "/") : $old_default_uri;
113
- $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
114
- $correct_slug = sanitize_title(get_the_title($post_id));
115
-
116
- // Process URI & slug
117
- $new_slug = wp_unique_post_slug($correct_slug, $post_id, get_post_status($post_id), get_post_type($post_id), null);
118
- $new_post_name = (in_array('post_names', $mode)) ? $new_slug : $old_post_name; // Post name is changed only in first mode
119
- $new_uri = (in_array('both', $mode)) ? $new_default_uri : str_replace($old_slug, $new_slug, $old_uri);
120
-
121
- // Check if native slug should be changed
122
- if(in_array('post_names', $mode) && ($old_post_name != $new_post_name)) {
123
- Permalink_Manager_Helper_Functions::update_slug_by_id($new_post_name, $post_id);
124
- }
125
-
126
- if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
127
- $old_uris[$post_id] = $new_uri;
128
- $updated_array[] = array('post_title' => get_the_title(), 'ID' => $post_id, 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
129
- $updated_slugs_count++;
130
- }
131
-
132
- // Do not store default values
133
- if($new_uri == $old_default_uri && is_array($old_uris)) {
134
- unset($old_uris[$post_id]);
135
- }
136
- }
137
-
138
- // Filter array before saving
139
- $old_uris = array_filter($old_uris);
140
- update_option('permalink-manager-uris', $old_uris);
141
-
142
- $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
143
- wp_reset_postdata();
144
- }
145
-
146
- return ($output) ? $output : "";
147
- }
148
-
149
- /**
150
- * Update all slugs & bases (bulk action)
151
- */
152
- static function update_all_permalinks() {
153
- // Setup needed variables
154
- $updated_slugs_count = 0;
155
- $updated_array = array();
156
- $alert_type = $alert_content = $errors = $main_content = '';
157
-
158
- $old_uris = get_option('permalink-manager-uris', array());
159
- $new_uris = isset($_POST['uri']) ? $_POST['uri'] : array();
160
-
161
- // Double check if the slugs and ids are stored in arrays
162
- if (!is_array($new_uris)) $new_uris = explode(',', $new_uris);
163
-
164
- if (!empty($new_uris)) {
165
- foreach($new_uris as $id => $new_uri) {
166
- // Prepare variables
167
- $this_post = get_post($id);
168
- $updated = '';
169
-
170
- // Prepare old values
171
- $old_default_uri = trim(str_replace(home_url("/"), "", get_permalink($id)), "/");
172
- $old_uri = isset($old_uris[$id]) ? trim($old_uris[$id], "/") : $old_default_uri;
173
-
174
- // Process new values; Empty entries will be treated as default values
175
- $new_default_uri = Permalink_Manager_Helper_Functions::get_uri($id, true);
176
- $new_uri = preg_replace('/\s+/', '', $new_uri);
177
- $new_uri = ($new_uri) ? trim($new_uri, "/") : $new_default_uri;
178
- $new_slug = (strpos($new_uri, '/') !== false) ? substr($new_uri, strrpos($new_uri, '/') + 1) : $new_uri;
179
-
180
- // Neither base nor slug was changed - continue
181
- if($new_uri == $old_uri) continue;
182
-
183
- if($new_uri != $old_uri) {
184
- $old_uris[$id] = $new_uri;
185
- $updated_array[] = array('post_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
186
- $updated_slugs_count++;
187
- }
188
-
189
- // Do not store default values
190
- if($new_uri == $old_default_uri) {
191
- unset($old_uris[$id]);
192
- }
193
-
194
- }
195
-
196
- // Filter array before saving
197
- $old_uris = array_filter($old_uris);
198
- update_option('permalink-manager-uris', $old_uris);
199
-
200
- $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
201
- }
202
-
203
- return ($output) ? $output : "";
204
- }
205
-
206
- /**
207
- * Update permastructs
208
- */
209
- static function update_permastructs() {
210
- // Setup needed variables
211
- $alert_type = $alert_content = $errors = $main_content = '';
212
- $permastructs = get_option('permalink-manager-permastructs', array());
213
- $new_permastructs = array_filter($_POST['permalink-manager']['custom-permastructs']);
214
-
215
- foreach($new_permastructs as $post_type => $new_permstruct) {
216
- $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type, true);
217
- $permastructs[$post_type] = trim(preg_replace('/\s+/', '', $new_permstruct), "/");
218
-
219
- // Do not save default permastructs
220
- if($default_permastruct == $new_permstruct) {
221
- unset($permastructs[$post_type]);
222
- }
223
- }
224
-
225
- update_option('permalink-manager-permastructs', $permastructs);
226
-
227
- return "";
228
- }
229
-
230
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/permalink-manager-base-editor.php DELETED
@@ -1,148 +0,0 @@
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
- ));
19
- }
20
-
21
- /**
22
- * Override the parent columns method. Defines the columns to use in your listing table
23
- */
24
- public function get_columns() {
25
- $columns = array(
26
- //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
27
- 'post_type' => __('Post Type', 'permalink-manager'),
28
- 'post_permalink_base' => __('Custom Permalink Base/Permastruct', 'permalink-manager')
29
- );
30
-
31
- return $columns;
32
- }
33
-
34
- /**
35
- * Hidden columns
36
- */
37
- public function get_hidden_columns() {
38
- return array('post_date_gmt');
39
- }
40
-
41
- /**
42
- * Sortable columns
43
- */
44
- public function get_sortable_columns() {
45
- return array(
46
- 'post_type' => array('post_title', false),
47
- );
48
- }
49
-
50
- /**
51
- * Data inside the columns
52
- */
53
- public function column_default( $item, $column_name ) {
54
- $custom_permastructs = get_option('permalink-manager-permastructs');
55
- $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($item['name'], true);
56
- $permastruct = isset($custom_permastructs[$item['name']]) ? $custom_permastructs[$item['name']] : '';
57
-
58
- switch( $column_name ) {
59
- case 'post_type':
60
- return "{$item['label']}<br /><small>({$item['name']})</small>";
61
-
62
- case 'post_permalink_base':
63
- $placeholder = $default_permastruct;
64
- $field_args = array('type' => 'text', 'placeholder' => $default_permastruct, 'default' => $permastruct, 'without_label' => true, 'input_class' => 'widefat', 'placeholder' => $placeholder);
65
- return Permalink_Manager_Helper_Functions::generate_option_field($item['name'], $field_args, 'custom-permastructs');
66
-
67
- default:
68
- return '';
69
- }
70
- }
71
-
72
- /**
73
- * Sort the data
74
- */
75
- private function sort_data( $a, $b ) {
76
- // Set defaults
77
- $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
78
- $result = strnatcasecmp( $a['name'], $b['name'] );
79
-
80
- return ($order === 'asc') ? $result : -$result;
81
- }
82
-
83
- /**
84
- * The button that allows to save updated slugs
85
- */
86
- function extra_tablenav( $which ) {
87
- $save_button = __( 'Save settings', 'permalink-manager' );
88
-
89
- echo '<div class="alignleft actions">';
90
- submit_button( $save_button, 'primary', "save_permastructs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'save_permastructs' ) );
91
- echo '</div>';
92
- }
93
-
94
- /**
95
- * Prepare the items for the table to process
96
- */
97
- public function prepare_items() {
98
- global $wpdb;
99
-
100
- $columns = $this->get_columns();
101
- $hidden = $this->get_hidden_columns();
102
- $sortable = $this->get_sortable_columns();
103
- $current_page = $this->get_pagenum();
104
-
105
- // Load options and fields
106
- $saved_options = get_option('permalink-manager');
107
- $saved_options = isset($saved_options['screen-options']) ? $saved_options['screen-options'] : array();
108
- $screen_options_fields = $this->screen_options_fields;
109
- $per_page = isset($saved_options['per_page']) ? $saved_options['per_page'] : $screen_options_fields['per_page']['default'];
110
-
111
- // Load all post types
112
- $all_data = Permalink_Manager_Helper_Functions::get_post_types_array('full');
113
-
114
- // Attachments are excluded
115
- unset($all_data['attachment']);
116
-
117
- // Will be used in pagination settings
118
- $total_items = count($all_data);
119
-
120
- // SQL query parameters
121
- $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
122
- $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
123
- $offset = ($current_page - 1) * $per_page;
124
-
125
- // Sort posts and count all posts
126
- usort( $all_data, array( &$this, 'sort_data' ) );
127
-
128
- // Pagination
129
- $data = array_slice($all_data, $offset, $per_page);
130
-
131
- $this->set_pagination_args( array(
132
- 'total_items' => $total_items,
133
- 'per_page' => $per_page
134
- ));
135
-
136
- $this->_column_headers = array($columns, $hidden, $sortable);
137
- $this->items = $data;
138
- }
139
-
140
- /**
141
- * This variable is assigned in permalink-manager.php before prepare_items() function is triggered, see permalinks_table_html() function
142
- */
143
- public function set_screen_option_fields($fields) {
144
- $this->screen_options_fields = $fields;
145
- }
146
-
147
- }
148
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/permalink-manager-editor.php DELETED
@@ -1,179 +0,0 @@
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_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
- ));
19
- }
20
-
21
- /**
22
- * Override the parent columns method. Defines the columns to use in your listing table
23
- */
24
- public function get_columns() {
25
- $columns = array(
26
- //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
27
- 'post_title' => __('Title', 'permalink-manager'),
28
- 'post_name' => __('Post Name (Native Slug)', 'permalink-manager'),
29
- //'post_date_gmt' => __('Date', 'permalink-manager'),
30
- 'base_with_slug' => __('Base & Slug (URI)', 'permalink-manager'),
31
- 'post_status' => __('Post Status', 'permalink-manager'),
32
- 'post_type' => __('Post Type', '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_title' => array('post_title', false),
51
- 'post_name' => array('post_name', false),
52
- 'post_status' => array('post_status', false),
53
- 'post_type' => array('post_type', false),
54
- );
55
- }
56
-
57
- /**
58
- * Data inside the columns
59
- */
60
- public function column_default( $item, $column_name ) {
61
-
62
- $base = Permalink_Manager_Helper_Functions::get_uri($item[ 'ID' ], false, false);
63
- $field_args_base = array('type' => 'text', 'default' => $base, 'without_label' => true, 'input_class' => 'small');
64
-
65
- switch( $column_name ) {
66
- case 'post_type':
67
- $post_type_labels = Permalink_Manager_Helper_Functions::get_post_types_array('full', $item['post_type']);
68
- return "{$post_type_labels['label']}<br /><small>({$post_type_labels['name']})</small>";
69
-
70
- case 'post_status':
71
- $post_statuses_array = get_post_statuses();
72
- return "{$post_statuses_array[$item[ $column_name ]]}<br /><small>({$item[ $column_name ]})</small>";
73
-
74
- case 'post_name':
75
- return $item[ 'post_name' ];
76
-
77
- case 'base_with_slug':
78
- return ($item['post_status'] != 'publish') ? '-' : Permalink_Manager_Helper_Functions::generate_option_field("uri[{$item['ID']}]", $field_args_base);
79
-
80
- case 'post_title':
81
- $edit_post = $item[ 'post_title' ];
82
- $edit_post .= '<small>' . Permalink_Manager_Helper_Functions::get_correct_permalink($item[ 'ID' ]) . '</small>';
83
- $edit_post .= '<div class="row-actions">';
84
- $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>';
85
- $edit_post .= '<span class="view"><a target="_blank" href="' . Permalink_Manager_Helper_Functions::get_correct_permalink($item[ 'ID' ]) . '" title="' . __('View', 'permalink-manager') . ' ' . $item[ 'post_title' ] . '" rel="permalink">' . __('View', 'permalink-manager') . '</a> | </span>';
86
- $edit_post .= '<span class="id">#' . $item[ 'ID' ] . '</span>';
87
- $edit_post .= '</div>';
88
- return $edit_post;
89
-
90
- default:
91
- return $item[ $column_name ];
92
- }
93
- }
94
-
95
- /**
96
- * Sort the data
97
- */
98
- private function sort_data( $a, $b ) {
99
- // Set defaults
100
- $orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'post_title';
101
- $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
102
- $result = strnatcasecmp( $a[$orderby], $b[$orderby] );
103
-
104
- return ($order === 'asc') ? $result : -$result;
105
- }
106
-
107
- /**
108
- * The button that allows to save updated slugs
109
- */
110
- function extra_tablenav( $which ) {
111
- $button_top = __( 'Update all slugs below', 'permalink-manager' );
112
- $button_bottom = __( 'Update all slugs above', 'permalink-manager' );
113
-
114
- echo '<div class="alignleft actions">';
115
- submit_button( ${"button_$which"}, 'primary', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
116
- echo '</div>';
117
- }
118
-
119
- /**
120
- * Prepare the items for the table to process
121
- */
122
- public function prepare_items() {
123
- global $wpdb;
124
-
125
- $columns = $this->get_columns();
126
- $hidden = $this->get_hidden_columns();
127
- $sortable = $this->get_sortable_columns();
128
- $current_page = $this->get_pagenum();
129
-
130
- // Load options and fields
131
- $saved_options = get_option('permalink-manager');
132
- $saved_options = isset($saved_options['screen-options']) ? $saved_options['screen-options'] : array();
133
- $screen_options_fields = $this->screen_options_fields;
134
- $per_page = isset($saved_options['per_page']) ? $saved_options['per_page'] : $screen_options_fields['per_page']['default'];
135
- $post_types_array = isset($saved_options['post_types']) ? $saved_options['post_types'] : $screen_options_fields['post_types']['default'];
136
- $post_types = "'" . implode("', '", $post_types_array) . "'";
137
- $post_statuses_array = isset($saved_options['post_statuses']) ? $saved_options['post_statuses'] : $screen_options_fields['post_statuses']['default'];
138
- $post_statuses = "'" . implode("', '", $post_statuses_array) . "'";
139
-
140
- // Will be used in pagination settings
141
- $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types)");
142
-
143
- // SQL query parameters
144
- $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
145
- $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
146
- $offset = ($current_page - 1) * $per_page;
147
-
148
- // Grab posts from database
149
- //$sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order LIMIT $per_page OFFSET $offset";
150
- $sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order";
151
- $all_data = $wpdb->get_results($sql_query, ARRAY_A);
152
-
153
- // Sort posts and count all posts
154
- usort( $all_data, array( &$this, 'sort_data' ) );
155
-
156
- $data = array_slice($all_data, $offset, $per_page);
157
-
158
- // Debug SQL query
159
- $debug_txt = "<textarea style=\"width:100%;height:300px\">{$sql_query} \n\nOffset: {$offset} \nPage: {$current_page}\nPer page: {$per_page} \nTotal: {$total_items}</textarea>";
160
- if(isset($_REQUEST['debug_editor_sql'])) { wp_die($debug_txt); }
161
-
162
- $this->set_pagination_args( array(
163
- 'total_items' => $total_items,
164
- 'per_page' => $per_page
165
- ));
166
-
167
- $this->_column_headers = array($columns, $hidden, $sortable);
168
- $this->items = $data;
169
- }
170
-
171
- /**
172
- * This variable is assigned in permalink-manager.php before prepare_items() function is triggered, see permalinks_table_html() function
173
- */
174
- public function set_screen_option_fields($fields) {
175
- $this->screen_options_fields = $fields;
176
- }
177
-
178
- }
179
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/permalink-manager-helper-functions.php DELETED
@@ -1,307 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Additional functions used in classes and another subclasses
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
- * Get post_types array
28
- */
29
- static function get_post_types_array($format = null, $cpt = null) {
30
- $post_types = get_post_types( array('public' => true), 'objects' );
31
-
32
- $post_types_array = array();
33
- if($format == 'full') {
34
- foreach ( $post_types as $post_type ) {
35
- $post_types_array[$post_type->name] = array('label' => $post_type->labels->name, 'name' => $post_type->name);
36
- }
37
- } else {
38
- foreach ( $post_types as $post_type ) {
39
- $post_types_array[$post_type->name] = $post_type->labels->name;
40
- }
41
- }
42
-
43
- return (empty($cpt)) ? $post_types_array : $post_types_array[$cpt];
44
- }
45
-
46
- /**
47
- * Generate the fields
48
- */
49
- static public function generate_option_field($name, $args, $group = null) {
50
- // Load values from options if needed
51
- $saved_values = get_option('permalink-manager');
52
-
53
- // Reset $fields variable
54
- $fields = '';
55
-
56
- // Load default value
57
- $default_value = (isset($args['default'])) ? $args['default'] : '';
58
- $label = (isset($args['label'])) ? $args['label'] : '';
59
- $placeholder = (isset($args['placeholder'])) ? "placeholder=\"{$args['placeholder']}\"" : '';
60
- $input_class = (isset($args['input_class'])) ? "class=\"{$args['input_class']}\"" : '';
61
- $container_class = (isset($args['container_class'])) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";
62
- $input_name = ($group) ? "permalink-manager[{$group}][{$name}]" : $name;
63
- $desc = (isset($args['desc'])) ? "<p class=\"field-desc\">{$args['desc']}</p>" : "";
64
-
65
- switch($args['type']) {
66
- case 'checkbox' :
67
- $fields .= '<div class="checkboxes">';
68
- foreach($args['choices'] as $value => $checkbox_label) {
69
- $all_checked = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $args['default'];
70
- $checked = in_array($value, $all_checked) ? "checked='checked'" : "";
71
- $fields .= "<label for='{$input_name}[]'><input type='checkbox' {$input_class} value='{$value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
72
- }
73
- $fields .= '</div>';
74
- break;
75
-
76
- case 'radio' :
77
- $fields .= '<div class="radios">';
78
- foreach($args['choices'] as $value => $checkbox_label) {
79
- $all_checked = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $args['default'];
80
- $checked = in_array($value, $all_checked) ? "checked='checked'" : "";
81
- $fields .= "<label for='{$input_name}[]'><input type='radio' {$input_class} value='{$value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
82
- }
83
- $fields .= '</div>';
84
- break;
85
-
86
- case 'number' :
87
- $value = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $default_value;
88
- $fields .= "<input type='number' {$input_class} value='{$value}' name='{$input_name}' />";
89
- break;
90
-
91
- case 'clearfix' :
92
- return "<div class=\"clearfix\"></div>";
93
-
94
- default :
95
- $value = (isset($saved_values[$group][$name])) ? $saved_values[$group][$name] : $default_value;
96
- $fields .= "<input type='text' {$input_class} value='{$value}' name='{$input_name}' {$placeholder}/>";
97
- }
98
-
99
- // Get all variables into one final variable
100
- if(isset($group) && (in_array($group, array('regenerate_slugs', 'find-replace')))) {
101
- $output = "<div{$container_class}>";
102
- $output .= "<h4>{$label}</h4>";
103
- $output .= "<div class='metabox-prefs'><div class='{$name}-container'>{$fields}</div></div>";
104
- $output .= $desc;
105
- $output .= "</div>";
106
- } else if (isset($args['without_label']) && $args['without_label'] == true) {
107
- $output = $fields;
108
- } else {
109
- $output = "<tr><th><label for='{$input_name}'>{$args['label']}</label></th>";
110
- $output .= "<td>{$fields}</td>";
111
- }
112
-
113
- return $output;
114
- }
115
-
116
- /**
117
- * Save option
118
- */
119
- static function save_option($field = null, $value = null) {
120
- $options = get_option('permalink-manager', array());
121
- if($field) {
122
- $options[$field] = $value;
123
- update_option('permalink-manager', $options);
124
- }
125
- }
126
-
127
- /**
128
- * Display the permalink in a better way
129
- */
130
- static function get_correct_permalink($id) {
131
- $old_uris = get_option('permalink-manager-uris');
132
- $permalink = isset($old_uris[$id]) ? home_url('/') . $old_uris[$id] : get_permalink($id);
133
-
134
- return $permalink;
135
- }
136
-
137
- /**
138
- * Check if the provided slug is unique and then update it with SQL query.
139
- */
140
- static function update_slug_by_id($slug, $id) {
141
- global $wpdb;
142
-
143
- // Update slug and make it unique
144
- $slug = (empty($slug)) ? sanitize_title(get_the_title($id)) : $slug;
145
- $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
146
- $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
147
-
148
- return $new_slug;
149
- }
150
-
151
- /**
152
- * Get permastruct
153
- */
154
- static function get_default_permastruct($post_type = 'page', $remove_post_tag = false) {
155
- global $wp_rewrite;
156
-
157
- // Get default permastruct
158
- if($post_type == 'page') {
159
- $permastruct = $wp_rewrite->get_page_permastruct();
160
- } else if($post_type == 'post') {
161
- $permastruct = get_option('permalink_structure');
162
- } else {
163
- $permastruct = $wp_rewrite->get_extra_permastruct($post_type);
164
- }
165
-
166
- return ($remove_post_tag) ? trim(str_replace(array("%postname%", "%pagename%", "%{$post_type}%"), "", $permastruct), "/") : $permastruct;
167
- }
168
-
169
- static function get_uri($post_id, $get_default = false, $remove_slug = true) {
170
-
171
- // Load all bases & post
172
- $post = isset($post_id->post_type) ? $post_id : get_post($post_id);
173
- $post_id = $post->ID;
174
- $post_type = $post->post_type;
175
- $post_name = $post->post_name;
176
-
177
- $all_uris = get_option('permalink-manager-uris');
178
- $all_permastructures = get_option('permalink-manager-permastructs');
179
- $options = get_option('permalink-manager');
180
- $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type);
181
-
182
- if($get_default) {
183
-
184
- if($get_default === 'native') {
185
- $permastruct = $default_permastruct;
186
- } else if($all_permastructures) {
187
- $permastruct = isset($all_permastructures[$post_type]) ? $all_permastructures[$post_type] : $default_permastruct;
188
- } else {
189
- $permastruct = isset($options['base-editor'][$post_type]) ? $options['base-editor'][$post_type] : $default_permastruct;
190
- }
191
-
192
- // Get options
193
- $default_base = ($permastruct) ? trim($permastruct, '/') : "";
194
-
195
- // Get the date
196
- $date = explode(" ",date('Y m d H i s', strtotime($post->post_date)));
197
-
198
- // Get the category (if needed)
199
- $category = '';
200
- if ( strpos($default_base, '%category%') !== false ) {
201
- $cats = get_the_category($post->ID);
202
- if ( $cats ) {
203
- usort($cats, '_usort_terms_by_ID'); // order by ID
204
- $category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
205
- $category_object = get_term( $category_object, 'category' );
206
- $category = $category_object->slug;
207
- if ( $parent = $category_object->parent )
208
- $category = get_category_parents($parent, false, '/', true) . $category;
209
- }
210
- // show default category in permalinks, without having to assign it explicitly
211
- if ( empty($category) ) {
212
- $default_category = get_term( get_option( 'default_category' ), 'category' );
213
- $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
214
- }
215
- }
216
-
217
- // Get the author (if needed)
218
- $author = '';
219
- if ( strpos($default_base, '%author%') !== false ) {
220
- $authordata = get_userdata($post->post_author);
221
- $author = $authordata->user_nicename;
222
- }
223
-
224
- // Fix for hierarchical CPT (start)
225
- $full_slug = get_page_uri($post);
226
- $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
227
-
228
- // Do the replacement (post tag is removed now to enable support for hierarchical CPT)
229
- $tags = array('%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', '%post_id%', '%category%', '%author%', $post_type_tag);
230
- $replacements = array($date[0], $date[1], $date[2], $date[3], $date[4], $date[5], $post->ID, $category, $author, '');
231
- $default_uri = str_replace($tags, $replacements, "{$default_base}/{$full_slug}");
232
-
233
- // Replace custom taxonomies
234
- $terms = get_taxonomies( array('public' => true, '_builtin' => false), 'names', 'and' );
235
- $taxonomies = $terms;
236
- if ( $taxonomies ) {
237
- foreach($taxonomies as $taxonomy) {
238
- $tag = "%{$taxonomy}%";
239
- $terms = wp_get_object_terms($post->ID, $taxonomy);
240
- if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
241
- $replacement = $terms[0]->slug;
242
- $default_uri = str_replace($tag, $replacement, $default_uri);
243
- }
244
- }
245
- }
246
- } else {
247
- $default_uri = str_replace(home_url("/"), "", get_permalink($post_id));
248
- }
249
-
250
- $uri = isset($all_uris[$post_id]) ? $all_uris[$post_id] : $default_uri;
251
- // Remove post_name from base (last part of string)
252
- $uri = ($remove_slug) ? str_replace($post_name, '', $uri) : $uri;
253
-
254
- $final_uri = ($get_default) ? $default_uri : $uri;
255
-
256
- // Clean URI
257
- $final_uri = preg_replace('/\s+/', '', $final_uri);
258
- $final_uri = str_replace('//', '/', $final_uri);
259
- $final_uri = trim($final_uri, "/");
260
-
261
- return $final_uri;
262
- }
263
-
264
- /**
265
- * Structure Tags & Rewrite functions
266
- */
267
- static function get_all_structure_tags($code = true, $seperator = ', ', $hide_slug_tags = true) {
268
- global $wp_rewrite;
269
-
270
- $tags = $wp_rewrite->rewritecode;
271
- $output = "";
272
- $last_tag_index = count($tags);
273
- $i = 1;
274
-
275
- // Hide slug tags
276
- if($hide_slug_tags) {
277
- $post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
278
- foreach($post_types as $post_type => $post_type_name) {
279
- $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
280
- // Find key with post type tag from rewritecode
281
- $key = array_search($post_type_tag, $tags);
282
- if($key) { unset($tags[$key]); }
283
- }
284
- }
285
-
286
- foreach($tags as $tag) {
287
- $sep = ($last_tag_index == $i) ? "" : $seperator;
288
- $output .= ($code) ? "<code>{$tag}</code>{$sep}" : "{$tag}{$sep}";
289
- $i++;
290
- }
291
-
292
- return $output;
293
- }
294
-
295
- static function get_post_tag($post_type) {
296
- // Get the post type (with fix for posts & pages)
297
- if($post_type == 'page') {
298
- $post_type_tag = '%pagename%';
299
- } else if ($post_type == 'post') {
300
- $post_type_tag = '%postname%';
301
- } else {
302
- $post_type_tag = "%{$post_type}%";
303
- }
304
- return $post_type_tag;
305
- }
306
-
307
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/permalink-manager-screen-options.php DELETED
@@ -1,40 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Additional Screen Options that helps to manage the permalinks in the table
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
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/core/permalink-manager-admin-functions.php ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Additional back-end functions related to Wordpress Dashboard UI
5
+ */
6
+ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
7
+
8
+ public $menu_name, $sections, $active_section, $active_subsection;
9
+ public $plugin_slug = PERMALINK_MANAGER_PLUGIN_SLUG;
10
+ public $plugin_basename = PERMALINK_MANAGER_BASENAME;
11
+
12
+ public function __construct() {
13
+ add_action( "admin_menu", array($this, "add_menu_page") );
14
+ add_action( 'admin_init', array($this, 'init') );
15
+
16
+ // Allow to edit URIs in posts, pages & CPT elements
17
+ add_filter( 'get_sample_permalink_html', array($this, 'edit_uri_box'), 10, 4 );
18
+ }
19
+
20
+ /**
21
+ * Hooks that should be triggered with "admin_init"
22
+ */
23
+ public function init() {
24
+ // Additional link in "Plugins" page
25
+ add_filter( "plugin_action_links_{$this->plugin_basename}", array($this, "plugins_page_links") );
26
+
27
+ // Detect current section
28
+ $this->sections = apply_filters('permalink-manager-sections', array());
29
+ $this->get_current_section();
30
+
31
+ // Save settings
32
+ $this->save_settings();
33
+ }
34
+
35
+ /**
36
+ * Get current section (only in plugin sections)
37
+ */
38
+ public function get_current_section() {
39
+ global $active_section, $active_subsection;
40
+
41
+ // 1. Get current section
42
+ if(isset($_GET['page']) && $_GET['page'] == $this->plugin_slug) {
43
+ if(isset($_POST['section'])) {
44
+ $this->active_section = $_POST['section'];
45
+ } else if(isset($_GET['section'])) {
46
+ $this->active_section = $_GET['section'];
47
+ } else {
48
+ $sections_names = array_keys($this->sections);
49
+ $this->active_section = $sections_names[0];
50
+ }
51
+ }
52
+
53
+ // 2. Get current subsection
54
+ if($this->active_section && isset($this->sections[$this->active_section]['subsections'])) {
55
+ if(isset($_POST['subsection'])) {
56
+ $this->active_subsection = $_POST['subsection'];
57
+ } else if(isset($_GET['subsection'])) {
58
+ $this->active_subsection = $_GET['subsection'];
59
+ } else {
60
+ $subsections_names = array_keys($this->sections[$this->active_section]['subsections']);
61
+ $this->active_subsection = $subsections_names[0];
62
+ }
63
+ }
64
+
65
+ // Set globals
66
+ $active_section = $this->active_section;
67
+ $active_subsection = $this->active_subsection;
68
+ }
69
+
70
+ /**
71
+ * Save settings
72
+ */
73
+ public function save_settings() {
74
+ global $permalink_manager_options, $permalink_manager_permastructs;
75
+
76
+ // Check if the form was submitted
77
+ if(empty($_POST)) { return; }
78
+
79
+ $post_fields = $_POST;
80
+ $new_options = array();
81
+ $helper_functions = new Permalink_Manager_Helper_Functions();
82
+
83
+ // 1. Sanitize the field values
84
+ foreach($post_fields as $option_name => $option_value) {
85
+ //$new_options[$option_name] = $helper_functions->multidimensional_array_map('sanitize_text_field', $option_value);
86
+ $new_options[$option_name] = $option_value;
87
+ }
88
+
89
+ // 2A. Save options/settings
90
+ if(isset($_POST['permalink-manager-options']) && wp_verify_nonce($_POST['permalink-manager-options'], 'save_settings')) {
91
+ // Override the global with settings
92
+ $permalink_manager_options = $new_options = array_filter($new_options);
93
+
94
+ // Save the settings in database
95
+ update_option('permalink-manager', $new_options);
96
+ }
97
+ // 2B. Save permastructs
98
+ else if(isset($_POST['permalink-manager-permastructs']) && wp_verify_nonce($_POST['permalink-manager-permastructs'], 'save_settings')) {
99
+ // Trim the trailing slashes & remove empty permastructures
100
+ $new_options = $helper_functions->multidimensional_array_map('untrailingslashit', $new_options['permastructures']);
101
+ $new_options = array_filter($new_options);
102
+
103
+ // Override the global with settings
104
+ $permalink_manager_permastructs = $new_options;
105
+
106
+ // Save the settings in database
107
+ update_option('permalink-manager-permastructs', $new_options);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Add menu page.
113
+ */
114
+ public function add_menu_page() {
115
+ $this->menu_name = add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', $this->plugin_slug, array($this, 'display_section') );
116
+
117
+ // Make sure thata the CSS and JS files are loaded only on plugin admin page.
118
+ add_action( 'admin_print_styles-' . $this->menu_name, array($this, 'enqueue_styles' ) );
119
+ add_action( 'admin_print_scripts-' . $this->menu_name, array($this, 'enqueue_scripts' ) );
120
+ }
121
+
122
+ /**
123
+ * Register the CSS file for the dashboard.
124
+ */
125
+ public function enqueue_styles() {
126
+ wp_enqueue_style( $this->plugin_slug, PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.css', array(), PERMALINK_MANAGER_VERSION, 'all' );
127
+ }
128
+
129
+ /**
130
+ * Register the JavaScript file for the dashboard.
131
+ */
132
+ public function enqueue_scripts() {
133
+ wp_enqueue_script( $this->plugin_slug, PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery' ), PERMALINK_MANAGER_VERSION, false );
134
+ }
135
+
136
+ /**
137
+ * Get admin url for the plugin
138
+ */
139
+ function get_admin_url($append = '') {
140
+ return menu_page_url( "{$this->plugin_slug}", false ) . $append;
141
+ }
142
+
143
+ /**
144
+ * Additional links on "Plugins" page
145
+ */
146
+ public function plugins_page_links($links) {
147
+ $links[] = '<a href="' . $this->get_admin_url() .'">' . __( 'Go To Permalink Manager', 'permalink-manager' ) . '</a>';
148
+ return $links;
149
+ }
150
+
151
+ /**
152
+ * Generate the fields
153
+ */
154
+ static public function generate_option_field($input_name, $args) {
155
+ global $permalink_manager_options;
156
+
157
+ // Reset $fields variables
158
+ $fields = $section_name = $field_name = '';
159
+
160
+ // Allow to filter the $args
161
+ $args = apply_filters('permalink-manager-field-args', $args, $input_name);
162
+
163
+ $default = (isset($args['default'])) ? $args['default'] : '';
164
+ $label = (isset($args['label'])) ? $args['label'] : '';
165
+ $placeholder = (isset($args['placeholder'])) ? "placeholder=\"{$args['placeholder']}\"" : '';
166
+ $readonly = (isset($args['readonly'])) ? "readonly=\"readonly\"" : '';
167
+ $rows = (isset($args['rows'])) ? "rows=\"{$rows}\"" : "rows=\"5\"";
168
+ $input_class = (isset($args['input_class'])) ? "class=\"{$args['input_class']}\"" : '';
169
+ $container_class = (isset($args['container_class'])) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";
170
+ $description = (isset($args['description'])) ? "<p class=\"field-description description\">{$args['description']}</p>" : "";
171
+ $append_content = (isset($args['append_content'])) ? "{$args['append_content']}" : "";
172
+
173
+ // Get the field value (if it is not set in $args)
174
+ if(isset($args['value']) && empty($args['value']) == false) {
175
+ $value = $args['value'];
176
+ } else {
177
+ // Extract the section and field name from $input_name
178
+ preg_match("/(.*)\[(.*)\]/", $input_name, $field_section_and_name);
179
+
180
+ if($field_section_and_name) {
181
+ $section_name = $field_section_and_name[1];
182
+ $field_name = $field_section_and_name[2];
183
+ $value = (isset($permalink_manager_options[$section_name][$field_name])) ? $permalink_manager_options[$section_name][$field_name] : $default;
184
+ } else {
185
+ $value = (isset($permalink_manager_options[$input_name])) ? $permalink_manager_options[$input_name] : $default;
186
+ }
187
+ }
188
+
189
+ switch($args['type']) {
190
+ case 'checkbox' :
191
+ $fields .= '<div class="checkboxes">';
192
+ foreach($args['choices'] as $choice_value => $checkbox_label) {
193
+ $checked = (is_array($value) && in_array($choice_value, $value)) ? "checked='checked'" : "";
194
+ $fields .= "<label for='{$input_name}[]'><input type='checkbox' {$input_class} value='{$choice_value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
195
+ }
196
+ $fields .= '</div>';
197
+
198
+ // Add helper checkboxes for bulk actions
199
+ if(isset($args['select_all']) || isset($args['unselect_all'])) {
200
+ $select_all_label = (!empty($args['select_all'])) ? $args['select_all'] : __('Select all', 'permalink-manager');
201
+ $unselect_all_label = (!empty($args['unselect_all'])) ? $args['unselect_all'] : __('Unselect all', 'permalink-manager');
202
+
203
+ $fields .= "<p class=\"checkbox_actions extra-links\">";
204
+ $fields .= (isset($args['select_all'])) ? "<a href=\"#\" class=\"select_all\">{$select_all_label}</a>&nbsp;" : "";
205
+ $fields .= (isset($args['unselect_all'])) ? "<a href=\"#\" class=\"unselect_all\">{$unselect_all_label}</a>" : "";
206
+ $fields .= "</p>";
207
+ }
208
+ break;
209
+
210
+ case 'radio' :
211
+ $fields .= '<div class="radios">';
212
+ foreach($args['choices'] as $choice_value => $checkbox_label) {
213
+ $checked = ($choice_value == $value) ? "checked='checked'" : "";
214
+ $fields .= "<label for='{$input_name}[]'><input type='radio' {$input_class} value='{$choice_value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
215
+ }
216
+ $fields .= '</div>';
217
+ break;
218
+
219
+ case 'select' :
220
+ $fields .= '<div class="select">';
221
+ $fields .= "<select name='{$input_name}' {$input_class}>";
222
+ foreach($args['choices'] as $choice_value => $checkbox_label) {
223
+ $selected = ($choice_value == $value) ? "selected='selected'" : "";
224
+ $fields .= "<option value='{$choice_value}' {$selected} />{$checkbox_label}</option>";
225
+ }
226
+ $fields .= '</select>';
227
+ $fields .= '</div>';
228
+ break;
229
+
230
+ case 'number' :
231
+ $fields .= "<input type='number' {$input_class} value='{$value}' name='{$input_name}' />";
232
+ break;
233
+
234
+ case 'textarea' :
235
+ $fields .= "<textarea {$input_class} name='{$input_name}' {$placeholder} {$readonly} {$rows}>{$value}</textarea>";
236
+ break;
237
+
238
+ case 'pre' :
239
+ $fields .= "<pre {$input_class}>{$value}</pre>";
240
+ break;
241
+
242
+ case 'clearfix' :
243
+ return "<div class=\"clearfix\"></div>";
244
+
245
+ default :
246
+ $fields .= "<input type='text' {$input_class} value='{$value}' name='{$input_name}' {$placeholder} {$readonly}/>";
247
+ }
248
+
249
+ // Get the final HTML output
250
+ if(isset($args['container']) && $args['container'] == 'tools') {
251
+ $output = "<div{$container_class}>";
252
+ $output .= "<h4>{$label}</h4>";
253
+ $output .= "<div class='{$input_name}-container'>{$fields}</div>";
254
+ $output .= $description;
255
+ $output .= $append_content;
256
+ $output .= "</div>";
257
+ } else if(isset($args['container']) && $args['container'] == 'row') {
258
+ $output = "<tr><th><label for='{$input_name}'>{$args['label']}</label></th>";
259
+ $output .= "<td>{$fields}{$description}</td></tr>";
260
+ $output .= ($append_content) ? "<tr class=\"appended-row\"><td colspan=\"2\">{$append_content}</td></tr>" : "";
261
+ } else {
262
+ $output = $fields . $append_content;
263
+ }
264
+
265
+ return apply_filters('permalink-manager-field-output', $output);
266
+ }
267
+
268
+ /**
269
+ * Allow to edit URIs from "Edit Post" admin pages
270
+ */
271
+ function edit_uri_box($html, $id, $new_title, $new_slug) {
272
+ global $post, $permalink_manager_uris;
273
+
274
+ // Do not change anything if post is not saved yet
275
+ if(empty($post->post_name)) return $html;
276
+ $default_uri = trim(str_replace(home_url("/"), "", get_permalink($id)), "/");
277
+ $uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $default_uri;
278
+
279
+ $html = preg_replace("/(<strong>(.*)<\/strong>)(.*)/is", "$1 ", $html);
280
+ $html .= home_url("/") . " <span id=\"editable-post-name\"><input type='text' value='{$uri}' name='custom_uri'/></span>";
281
+ return $html;
282
+ }
283
+
284
+ /**
285
+ * Display the form
286
+ */
287
+ static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array()) {
288
+ // 1. Check if the content will be displayed in columns and button details
289
+ switch($container) {
290
+ case 'columns-3' :
291
+ $wrapper_class = 'columns-container';
292
+ $form_column_class = 'column column-2_3';
293
+ $sidebar_class = 'column column-1_3';
294
+ break;
295
+ // there will be more cases in future ...
296
+ default :
297
+ $wrapper_class = $form_column_class = $sidebar_class = '';
298
+ }
299
+
300
+ // 2. Process the array with button and nonce field settings
301
+ $button_text = (!empty($button['text'])) ? $button['text'] : '';
302
+ $button_class = (!empty($button['class'])) ? $button['class'] : '';
303
+ $nonce_action = (!empty($nonce['action'])) ? $nonce['action'] : '';
304
+ $nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : '';
305
+
306
+ // 2. Now get the HTML output (start section row container)
307
+ $output = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : '';
308
+
309
+ // 3. Start fields' section
310
+ $output .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : "";
311
+ $output .= "<form method=\"POST\">";
312
+
313
+ // Loop through all fields assigned to this section
314
+ foreach($fields as $field_name => $field) {
315
+ $field['container'] = 'tools';
316
+
317
+ // A. Detect fields group
318
+ if(isset($field['group'])) {
319
+ $output .= "<div class=\"columns-container\">";
320
+ // Loop through all fields assigned to this section
321
+ foreach($field['group'] as $groupped_field_name => $groupped_field) {
322
+ $groupped_field['container'] = 'tools';
323
+ $output .= self::generate_option_field($groupped_field_name, $groupped_field);
324
+ }
325
+ $output .= "</div>";
326
+ }
327
+ // B. Detect section
328
+ else if(isset($field['section_name'])) {
329
+ $output .= "<h4>{$field['section_name']}</h4>";
330
+ $output .= (isset($section['description'])) ? "<p class=\"description\">{$field['description']}</p>" : "";
331
+ $output .= "<table class=\"form-table\">";
332
+
333
+ // Loop through all fields assigned to this section
334
+ foreach($field['fields'] as $section_field_id => $section_field) {
335
+ $section_field_name = "{$field_name}[$section_field_id]";
336
+ $section_field['container'] = 'row';
337
+
338
+ $output .= self::generate_option_field($section_field_name, $section_field);
339
+ }
340
+
341
+ $output .= "</table>";
342
+ }
343
+ // C. Display single field
344
+ else {
345
+ $output .= self::generate_option_field($field_name, $field);
346
+ }
347
+ }
348
+
349
+ // End the fields' section + add button & nonce fields
350
+ $output .= ($nonce_action && $nonce_name) ? wp_nonce_field($nonce_action, $nonce_name, true, true) : "";
351
+ $output .= ($button_text) ? get_submit_button($button_text, $button_class, '', false) : "";
352
+ $output .= '</form>';
353
+ $output .= ($form_column_class) ? "</div>" : "";
354
+
355
+ // 4. Display some notes
356
+ if($sidebar_class && $sidebar) {
357
+ $output .= "<div class=\"{$sidebar_class}\">";
358
+ $output .= "<div class=\"section-notes\">";
359
+ $output .= $sidebar;
360
+ $output .= "</div>";
361
+ $output .= "</div>";
362
+ }
363
+
364
+ // 5. End the section row container
365
+ $output .= ($wrapper_class) ? "</div>" : "";
366
+
367
+ return $output;
368
+ }
369
+
370
+ /**
371
+ * Display the plugin sections.
372
+ */
373
+ public function display_section() {
374
+ global $wpdb, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
375
+
376
+ $output = "<div id=\"permalink-manager\" class=\"wrap\">";
377
+
378
+ // Display alerts and another content if needed and the plugin header
379
+ $output .= $permalink_manager_before_sections_html;
380
+ $output .= "<h2 id=\"plugin-name-heading\">" . PERMALINK_MANAGER_PLUGIN_NAME . " <a href=\"" . PERMALINK_MANAGER_WEBSITE ."\" target=\"_blank\">" . __('by Maciej Bis', 'permalink-manager') . "</a></h2>";
381
+
382
+ // Display the tab navigation
383
+ $output .= "<div id=\"permalink-manager-tab-nav\" class=\"nav-tab-wrapper\">";
384
+ foreach($this->sections as $section_name => $section_properties) {
385
+ $active_class = ($this->active_section === $section_name) ? 'nav-tab-active nav-tab' : 'nav-tab';
386
+ $section_url = $this->get_admin_url("&section={$section_name}");
387
+
388
+ $output .= "<a href=\"{$section_url}\" class=\"{$active_class}\">{$section_properties['name']}</a>";
389
+ }
390
+ $output .= "</div>";
391
+
392
+ // Display addidional navigation for subsections
393
+ if(isset($this->sections[$this->active_section]['subsections'])) {
394
+ $output .= "<ul class=\"subsubsub\">";
395
+ foreach ($this->sections[$this->active_section]['subsections'] as $subsection_name => $subsection) {
396
+ $active_class = ($this->active_subsection === $subsection_name) ? 'current' : '';
397
+ $subsection_url = $this->get_admin_url("&section={$this->active_section}&subsection={$subsection_name}");
398
+
399
+ $output .= "<li><a href=\"{$subsection_url}\" class=\"{$active_class}\">{$subsection['name']}</a></li>";
400
+ }
401
+ $output .= "</ul>";
402
+ }
403
+
404
+ // Now display the active section
405
+ $output .= "<div id=\"permalink-manager-sections\">";
406
+ $active_section_array = (isset($this->sections[$this->active_section])) ? $this->sections[$this->active_section] : "";
407
+
408
+ // A. Execute the function assigned to the subsection
409
+ if(isset($active_section_array['subsections'][$this->active_subsection]['function'])) {
410
+ $class_name = $active_section_array['subsections'][$this->active_subsection]['function']['class'];
411
+ $section_object = new $class_name();
412
+
413
+ $section_content = call_user_func(array($section_object, $active_section_array['subsections'][$this->active_subsection]['function']['method']));
414
+ }
415
+ // B. Execute the function assigned to the section
416
+ else if(isset($active_section_array['function'])) {
417
+ $class_name = $active_section_array['function']['class'];
418
+ $section_object = new $class_name();
419
+
420
+ $section_content = call_user_func(array($section_object, $active_section_array['function']['method']));
421
+ }
422
+ // C. Display the raw HTMl output
423
+ else {
424
+ $section_content = (isset($active_section_array['html'])) ? $active_section_array['html'] : "";
425
+ }
426
+
427
+ $output .= "<div data-section=\"{$this->active_section}\" id=\"{$this->active_section}\">{$section_content}</div>";
428
+ $output .= "</div>";
429
+
430
+ // Display alerts and another content if needed and close .wrap container
431
+ $output .= $permalink_manager_after_sections_html;
432
+ $output .= "</div>";
433
+
434
+ echo $output;
435
+ }
436
+
437
+ /**
438
+ * Display error/info message
439
+ */
440
+ static function get_alert_message($alert_content, $alert_type, $dismissable = true) {
441
+ $class = ($dismissable) ? "is-dismissible" : "";
442
+ $output = sprintf( "<div class=\"{$alert_type} notice {$class}\"> %s</div>", wpautop($alert_content) );
443
+
444
+ return $output;
445
+ }
446
+
447
+ /**
448
+ * Display the table with updated slugs after one of the actions is triggered
449
+ */
450
+ static function display_updated_slugs($updated_array) {
451
+ // Check if slugs should be displayed
452
+ $first_slug = reset($updated_array);
453
+
454
+ $header_footer = '<tr>';
455
+ $header_footer .= '<th class="column-primary">' . __('Title', 'permalink-manager') . '</th>';
456
+ $header_footer .= '<th>' . __('Old URI', 'permalink-manager') . '</th>';
457
+ $header_footer .= '<th>' . __('New URI', 'permalink-manager') . '</th>';
458
+ $header_footer .= (isset($first_slug['old_slug'])) ? '<th>' . __('Old Slug', 'permalink-manager') . '</th>' : "";
459
+ $header_footer .= (isset($first_slug['new_slug'])) ? '<th>' . __('New Slug', 'permalink-manager') . '</th>' : "";
460
+ $header_footer .= '</tr>';
461
+
462
+ $updated_slugs_count = 0;
463
+ $main_content = "";
464
+ foreach($updated_array as $row) {
465
+ // Odd/even class
466
+ $updated_slugs_count++;
467
+ $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
468
+ $permalink = home_url("{$row['new_uri']}");
469
+
470
+ $main_content .= "<tr{$alternate_class}>";
471
+ $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['post_title'] . "<a target=\"_blank\" href=\"{$permalink}\"><span class=\"small\">{$permalink}</span></a>" . '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __('Show more details', 'permalink-manager') . '</span></button></td>';
472
+ $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . $row['old_uri'] . '</td>';
473
+ $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . $row['new_uri'] . '</td>';
474
+ $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . $row['old_slug'] . '</td>' : "";
475
+ $main_content .= (isset($row['new_slug'])) ? '<td data-colname="' . __('New Slug', 'permalink-manager') . '">' . $row['new_slug'] . '</td>' : "";
476
+ $main_content .= '</tr>';
477
+ }
478
+
479
+ // Merge header, footer and content
480
+ $output = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
481
+ $output .= '<table class="widefat wp-list-table updated-slugs-table">';
482
+ $output .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
483
+ $output .= '</table>';
484
+
485
+ return $output ;
486
+ }
487
+
488
+ }
includes/core/permalink-manager-helper-functions.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Additional functions used in classes and another subclasses
5
+ */
6
+ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
7
+
8
+ public function __construct() { }
9
+
10
+ /**
11
+ * Support for multidimensional arrays - array_map()
12
+ */
13
+ static function multidimensional_array_map($function, $input) {
14
+ $output = array();
15
+
16
+ if(is_array($input)) {
17
+ foreach ($input as $key => $val) {
18
+ $output[$key] = (is_array($val) ? self::multidimensional_array_map($function, $val) : $function($val));
19
+ }
20
+ } else {
21
+ $output = $function($input);
22
+ }
23
+
24
+ return $output;
25
+ }
26
+
27
+ /**
28
+ * Get primary term (by Yoast SEO)
29
+ */
30
+ static function get_primary_term($post_id, $taxonomy) {
31
+ global $permalink_manager_options;
32
+
33
+ if($permalink_manager_options['miscellaneous']['yoast_primary_term'] == 1 && class_exists('WPSEO_Primary_Term')) {
34
+ $primary_term = new WPSEO_Primary_Term($taxonomy, $post_id);
35
+ $primary_term = get_term($primary_term->get_primary_term());
36
+ return (!is_wp_error($primary_term)) ? $primary_term->slug : "";
37
+ } else {
38
+ return '';
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Get post_types array
44
+ */
45
+ static function get_post_types_array($format = null, $cpt = null) {
46
+ $post_types = apply_filters('permalink-manager-post-types', get_post_types( array('public' => true), 'objects'));
47
+
48
+ $post_types_array = array();
49
+ if($format == 'full') {
50
+ foreach ( $post_types as $post_type ) {
51
+ $post_types_array[$post_type->name] = array('label' => $post_type->labels->name, 'name' => $post_type->name);
52
+ }
53
+ } else {
54
+ foreach ( $post_types as $post_type ) {
55
+ $post_types_array[$post_type->name] = $post_type->labels->name;
56
+ }
57
+ }
58
+
59
+ return (empty($cpt)) ? $post_types_array : $post_types_array[$cpt];
60
+ }
61
+
62
+ /**
63
+ * Get permastruct
64
+ */
65
+ static function get_default_permastruct($post_type = 'page', $remove_post_tag = false) {
66
+ global $wp_rewrite;
67
+
68
+ // Get default permastruct
69
+ if($post_type == 'page') {
70
+ $permastruct = $wp_rewrite->get_page_permastruct();
71
+ } else if($post_type == 'post') {
72
+ $permastruct = get_option('permalink_structure');
73
+ } else {
74
+ $permastruct = $wp_rewrite->get_extra_permastruct($post_type);
75
+ }
76
+
77
+ return ($remove_post_tag) ? trim(str_replace(array("%postname%", "%pagename%", "%{$post_type}%"), "", $permastruct), "/") : $permastruct;
78
+ }
79
+
80
+ /**
81
+ * Structure Tags & Rewrite functions
82
+ */
83
+ static function get_all_structure_tags($code = true, $seperator = ', ', $hide_slug_tags = true) {
84
+ global $wp_rewrite;
85
+
86
+ $tags = $wp_rewrite->rewritecode;
87
+ $output = "";
88
+ $last_tag_index = count($tags);
89
+ $i = 1;
90
+
91
+ // Hide slug tags
92
+ if($hide_slug_tags) {
93
+ $post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
94
+ foreach($post_types as $post_type => $post_type_name) {
95
+ $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
96
+ // Find key with post type tag from rewritecode
97
+ $key = array_search($post_type_tag, $tags);
98
+ if($key) { unset($tags[$key]); }
99
+ }
100
+ }
101
+
102
+ foreach($tags as $tag) {
103
+ $sep = ($last_tag_index == $i) ? "" : $seperator;
104
+ $output .= ($code) ? "<code>{$tag}</code>{$sep}" : "{$tag}{$sep}";
105
+ $i++;
106
+ }
107
+
108
+ return $output;
109
+ }
110
+
111
+ static function get_post_tag($post_type) {
112
+ // Get the post type (with fix for posts & pages)
113
+ if($post_type == 'page') {
114
+ $post_type_tag = '%pagename%';
115
+ } else if ($post_type == 'post') {
116
+ $post_type_tag = '%postname%';
117
+ } else {
118
+ $post_type_tag = "%{$post_type}%";
119
+ }
120
+ return $post_type_tag;
121
+ }
122
+
123
+ }
includes/core/permalink-manager-post-uri-functions.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Additional functions used in classes and another subclasses
5
+ */
6
+ class Permalink_Manager_Post_URI_Functions extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( '_get_page_link', array($this, 'custom_post_permalinks'), 999, 2);
10
+ add_filter( 'page_link', array($this, 'custom_post_permalinks'), 999, 2);
11
+ add_filter( 'post_link', array($this, 'custom_post_permalinks'), 999, 2);
12
+ add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 999, 2);
13
+ add_filter( 'permalink-manager-uris', array($this, 'exclude_homepage'), 999, 2);
14
+ add_action( 'save_post', array($this, 'update_post_uri'), 10, 3 );
15
+ add_action( 'wp_trash_post', array($this, 'remove_post_uri'), 10, 3 );
16
+ }
17
+
18
+ /**
19
+ * Change permalinks for posts, pages & custom post types
20
+ */
21
+ function custom_post_permalinks($permalink, $post) {
22
+ global $wp_rewrite, $permalink_manager_uris;
23
+
24
+ $post = (is_integer($post)) ? get_post($post) : $post;
25
+ $post_type = $post->post_type;
26
+
27
+ // Do not change permalink of frontpage
28
+ if(get_option('page_on_front') == $post->ID) { return $permalink; }
29
+ if(isset($permalink_manager_uris[$post->ID])) $permalink = home_url('/') . $permalink_manager_uris[$post->ID];
30
+
31
+ return $permalink;
32
+ }
33
+
34
+ /**
35
+ * Display the permalink in a better way
36
+ */
37
+ static function get_correct_permalink($id) {
38
+ global $permalink_manager_uris;
39
+ $permalink = isset($permalink_manager_uris[$id]) ? home_url('/') . $permalink_manager_uris[$id] : get_permalink($id);
40
+
41
+ return $permalink;
42
+ }
43
+
44
+ /**
45
+ * Check if the provided slug is unique and then update it with SQL query.
46
+ */
47
+ static function update_slug_by_id($slug, $id) {
48
+ global $wpdb;
49
+
50
+ // Update slug and make it unique
51
+ $slug = (empty($slug)) ? sanitize_title(get_the_title($id)) : $slug;
52
+ $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
53
+ $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
54
+
55
+ return $new_slug;
56
+ }
57
+
58
+ /**
59
+ * Get the active URI
60
+ */
61
+ static function get_post_uri($post_id) {
62
+ global $permalink_manager_uris;
63
+
64
+ // Check if input is post object
65
+ $post_id = (isset($post_id->ID)) ? $post_id->ID : $post_id;
66
+
67
+ $final_uri = isset($permalink_manager_uris[$post_id]) ? $permalink_manager_uris[$post_id] : self::get_default_post_uri($post_id);
68
+ return $final_uri;
69
+ }
70
+
71
+ /**
72
+ * Get the default (not overwritten by the user) or native URI (unfiltered)
73
+ */
74
+ static function get_default_post_uri($post, $native_uri = false) {
75
+ global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs;
76
+
77
+ // Load all bases & post
78
+ $post = is_object($post) ? $post : get_post($post);
79
+ $post_id = $post->ID;
80
+ $post_type = $post->post_type;
81
+ $post_name = $post->post_name;
82
+
83
+ // Get the permastruct
84
+ $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type);
85
+
86
+ if($native_uri) {
87
+ $permastruct = $default_permastruct;
88
+ } else if($permalink_manager_permastructs) {
89
+ $permastruct = isset($permalink_manager_permastructs[$post_type]) ? $permalink_manager_permastructs[$post_type] : $default_permastruct;
90
+ } else {
91
+ $permastruct = isset($permalink_manager_options['base-editor'][$post_type]) ? $permalink_manager_options['base-editor'][$post_type] : $default_permastruct;
92
+ }
93
+ $default_base = (!empty($permastruct)) ? trim($permastruct, '/') : "";
94
+
95
+ // 1A. Get the date
96
+ $date = explode(" ",date('Y m d H i s', strtotime($post->post_date)));
97
+
98
+ // 1B. Get the category slug (if needed)
99
+ $category = '';
100
+ if ( strpos($default_base, '%category%') !== false ) {
101
+
102
+ // I. Try to use Yoast SEO Primary Term
103
+ $category = (Permalink_Manager_Helper_Functions::get_primary_term($post->ID, 'category'));
104
+
105
+ // II. Get the first assigned category
106
+ if(empty($category)) {
107
+ $cats = get_the_category($post->ID);
108
+ if ($cats) {
109
+ usort($cats, '_usort_terms_by_ID'); // order by ID
110
+ $category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
111
+ $category_object = get_term( $category_object, 'category' );
112
+ $category = $category_object->slug;
113
+ if ( $parent = $category_object->parent )
114
+ $category = get_category_parents($parent, false, '/', true) . $category;
115
+ }
116
+ }
117
+
118
+ // III. Show default category in permalinks, without having to assign it explicitly
119
+ if(empty($category)) {
120
+ $default_category = get_term( get_option( 'default_category' ), 'category' );
121
+ $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
122
+ }
123
+ }
124
+
125
+ // 1C. Get the author (if needed)
126
+ $author = '';
127
+ if ( strpos($default_base, '%author%') !== false ) {
128
+ $authordata = get_userdata($post->post_author);
129
+ $author = $authordata->user_nicename;
130
+ }
131
+
132
+ // 2. Fix for hierarchical CPT (start)
133
+ $full_slug = ($native_uri == false) ? apply_filters('permalink_manager_filter_default_post_slug', get_page_uri($post), $post) : get_page_uri($post);
134
+ $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
135
+
136
+ // 3A. Do the replacement (post tag is removed now to enable support for hierarchical CPT)
137
+ $tags = array('%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', '%post_id%', '%category%', '%author%', $post_type_tag);
138
+ $replacements = array($date[0], $date[1], $date[2], $date[3], $date[4], $date[5], $post->ID, $category, $author, '');
139
+ $default_uri = str_replace($tags, $replacements, "{$default_base}/{$full_slug}");
140
+
141
+ // 3B. Replace custom taxonomies
142
+ $terms = get_taxonomies( array('public' => true, '_builtin' => false), 'names', 'and' );
143
+ $taxonomies = $terms;
144
+ if ( $taxonomies ) {
145
+ foreach($taxonomies as $taxonomy) {
146
+ // A. Try to use Yoast SEO Primary Term
147
+ $category = (Permalink_Manager_Helper_Functions::get_primary_term($post->ID, $taxonomy));
148
+
149
+ // B. Get the first assigned term to this taxonomy
150
+ if(empty($replacement)) {
151
+ $terms = wp_get_object_terms($post->ID, $taxonomy);
152
+ $replacement = (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) ? $terms[0]->slug : "";
153
+ }
154
+
155
+ // Do the replacement
156
+ $default_uri = ($replacement) ? str_replace("%{$taxonomy}%", $replacement, $default_uri) : $default_uri;
157
+ }
158
+ }
159
+
160
+ $default_uri = preg_replace('/\s+/', '', $default_uri);
161
+ $default_uri = str_replace('//', '/', $default_uri);
162
+ $default_uri = trim($default_uri, "/");
163
+
164
+ return $default_uri;
165
+ }
166
+
167
+ /**
168
+ * The homepage should not use URI
169
+ */
170
+ function exclude_homepage($uris) {
171
+ // Find the homepage URI
172
+ $homepage_id = get_option('page_on_front');
173
+ if(isset($uris[$homepage_id])) { unset($uris[$homepage_id]); }
174
+
175
+ return $uris;
176
+ }
177
+
178
+ /**
179
+ * Find & replace (bulk action)
180
+ */
181
+ static function posts_find_and_replace() {
182
+ global $wpdb, $permalink_manager_uris;
183
+
184
+ // Reset variables
185
+ $updated_slugs_count = 0;
186
+ $updated_array = array();
187
+ $alert_type = $alert_content = $errors = '';
188
+
189
+ // Prepare default variables from $_POST object
190
+ $old_string = esc_sql($_POST['old_string']);
191
+ $new_string = esc_sql($_POST['new_string']);
192
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : array('both');
193
+ $post_types_array = ($_POST['post_types']);
194
+ $post_statuses_array = ($_POST['post_statuses']);
195
+ $post_types = implode("', '", $post_types_array);
196
+ $post_statuses = implode("', '", $post_statuses_array);
197
+
198
+ // Save the rows before they are updated to an array
199
+ $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
200
+
201
+ // Now if the array is not empty use IDs from each subarray as a key
202
+ if($posts_to_update && empty($errors)) {
203
+ foreach ($posts_to_update as $row) {
204
+
205
+ // Prepare variables
206
+ $old_post_name = $row['post_name'];
207
+ $native_uri = self::get_default_post_uri($row['ID'], true);
208
+ $default_uri = self::get_default_post_uri($row['ID']);
209
+ $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $default_uri;
210
+ $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
211
+ $old_base = (strpos($old_uri, '/') !== false) ? substr($old_uri, 0, strrpos( $old_uri, '/') ) : '';
212
+
213
+ // Process URI & slug
214
+ $new_slug = str_replace($old_string, $new_string, $old_slug);
215
+ $new_base = str_replace($old_string, $new_string, $old_base);
216
+ $new_uri = (in_array($mode, array('both'))) ? trim("{$new_base}/{$new_slug}", "/") : trim("{$old_base}/{$new_slug}", "/");
217
+ $new_post_name = (in_array($mode, array('post_names'))) ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
218
+
219
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
220
+
221
+ // Check if native slug should be changed
222
+ if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
223
+ self::update_slug_by_id($new_post_name, $row['ID']);
224
+ }
225
+
226
+ if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
227
+ $permalink_manager_uris[$row['ID']] = $new_uri;
228
+ $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
229
+ $updated_slugs_count++;
230
+ }
231
+
232
+ // Do not store default values
233
+ if(isset($permalink_manager_uris[$row['ID']]) && ($new_uri == $native_uri)) {
234
+ unset($permalink_manager_uris[$row['ID']]);
235
+ }
236
+ }
237
+
238
+ // Filter array before saving
239
+ $permalink_manager_uris = array_filter($permalink_manager_uris);
240
+ update_option('permalink-manager-uris', $permalink_manager_uris);
241
+
242
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
243
+ wp_reset_postdata();
244
+ }
245
+
246
+ return ($output) ? $output : "";
247
+ }
248
+
249
+ /**
250
+ * Regenerate slugs & bases (bulk action)
251
+ */
252
+ static function posts_regenerate_all_permalinks() {
253
+ global $wpdb, $permalink_manager_uris, $permalink_manager_permastructs;
254
+
255
+ // Setup needed variables
256
+ $updated_slugs_count = 0;
257
+ $updated_array = array();
258
+ $alert_type = $alert_content = $errors = '';
259
+
260
+ $post_types_array = ($_POST['post_types']) ? ($_POST['post_types']) : '';
261
+ $post_statuses_array = ($_POST['post_statuses']) ? $_POST['post_statuses'] : '';
262
+ $post_types = implode("', '", $post_types_array);
263
+ $post_statuses = implode("', '", $post_statuses_array);
264
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : 'both';
265
+
266
+ // Save the rows before they are updated to an array
267
+ $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, post_type, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
268
+
269
+ // Now if the array is not empty use IDs from each subarray as a key
270
+ if($posts_to_update && empty($errors)) {
271
+ foreach ($posts_to_update as $row) {
272
+ $updated = 0;
273
+
274
+ // Prepare variables
275
+ $old_post_name = $row['post_name'];
276
+ $native_uri = self::get_default_post_uri($row['ID'], true);
277
+ $default_uri = self::get_default_post_uri($row['ID']);
278
+ $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
279
+ $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
280
+ $correct_slug = sanitize_title($row['post_title']);
281
+
282
+ // Process URI & slug
283
+ $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
284
+ $new_post_name = (in_array($mode, array('post_names'))) ? $new_slug : $old_post_name; // Post name is changed only in first mode
285
+ $new_uri = (in_array($mode, array('both'))) ? $default_uri : str_replace($old_slug, $new_slug, $old_uri);
286
+
287
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
288
+
289
+ // Check if native slug should be changed
290
+ if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
291
+ self::update_slug_by_id($new_post_name, $row['ID']);
292
+ }
293
+
294
+ if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
295
+ $permalink_manager_uris[$row['ID']] = $new_uri;
296
+ $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
297
+ $updated_slugs_count++;
298
+ }
299
+
300
+ // Do not store default values
301
+ if(isset($permalink_manager_uris[$row['ID']]) && ($new_uri == $native_uri)) {
302
+ unset($permalink_manager_uris[$row['ID']]);
303
+ }
304
+ }
305
+
306
+ // Filter array before saving
307
+ $permalink_manager_uris = array_filter($permalink_manager_uris);
308
+ update_option('permalink-manager-uris', $permalink_manager_uris);
309
+
310
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
311
+ wp_reset_postdata();
312
+ }
313
+
314
+ return (!empty($output)) ? $output : "";
315
+ }
316
+
317
+ /**
318
+ * Update all slugs & bases (bulk action)
319
+ */
320
+ static public function posts_update_all_permalinks() {
321
+ global $permalink_manager_uris;
322
+
323
+ // Setup needed variables
324
+ $updated_slugs_count = 0;
325
+ $updated_array = array();
326
+
327
+ $old_uris = $permalink_manager_uris;
328
+ $new_uris = isset($_POST['uri']) ? $_POST['uri'] : array();
329
+
330
+ // Double check if the slugs and ids are stored in arrays
331
+ if (!is_array($new_uris)) $new_uris = explode(',', $new_uris);
332
+
333
+ if (!empty($new_uris)) {
334
+ foreach($new_uris as $id => $new_uri) {
335
+ // Prepare variables
336
+ $this_post = get_post($id);
337
+ $updated = '';
338
+
339
+ // Get default & native URL
340
+ $native_uri = self::get_default_post_uri($id, true);
341
+ $default_uri = self::get_default_post_uri($id);
342
+
343
+ $old_uri = isset($old_uris[$id]) ? trim($old_uris[$id], "/") : $native_uri;
344
+
345
+ // Process new values - empty entries will be treated as default values
346
+ $new_uri = preg_replace('/\s+/', '', $new_uri);
347
+ $new_uri = (!empty($new_uri)) ? trim($new_uri, "/") : $default_uri;
348
+ $new_slug = (strpos($new_uri, '/') !== false) ? substr($new_uri, strrpos($new_uri, '/') + 1) : $new_uri;
349
+
350
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
351
+
352
+ // Do not store native URIs
353
+ if($new_uri == $native_uri) {
354
+ unset($old_uris[$id]);
355
+ }
356
+
357
+ if($new_uri != $old_uri) {
358
+ $old_uris[$id] = $new_uri;
359
+ $updated_array[] = array('post_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
360
+ $updated_slugs_count++;
361
+ }
362
+
363
+ }
364
+
365
+ // Filter array before saving & append the global
366
+ $old_uris = $permalink_manager_uris = array_filter($old_uris);
367
+ update_option('permalink-manager-uris', $old_uris);
368
+
369
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
370
+ }
371
+
372
+ return ($output) ? $output : "";
373
+ }
374
+
375
+ /**
376
+ * Update URI from "Edit Post" admin page
377
+ */
378
+ function update_post_uri($post_id, $post, $update) {
379
+ global $permalink_manager_uris;
380
+
381
+ // Ignore trashed items
382
+ if($post->post_status == 'trash') return;
383
+
384
+ // Fix for revisions
385
+ $is_revision = wp_is_post_revision($post_id);
386
+ $post_id = ($is_revision) ? $is_revision : $post_id;
387
+ $post = get_post($post_id);
388
+
389
+ $native_uri = self::get_default_post_uri($post, true);
390
+ $old_uri = (isset($permalink_manager_uris[$post->ID])) ? $permalink_manager_uris[$post->ID] : $native_uri;
391
+ $new_uri = '';
392
+
393
+ // Check if user changed URI (available after post is saved)
394
+ if(isset($_POST['custom_uri'])) {
395
+ $new_uri = trim($_POST['custom_uri'], "/");
396
+ }
397
+
398
+ // A little hack (if user removes whole URI from input) ...
399
+ $new_uri = ($new_uri) ? $new_uri : self::get_post_uri($post);
400
+
401
+ // Do not store default values
402
+ if(isset($permalink_manager_uris[$post->ID]) && ($new_uri == $native_uri)) {
403
+ unset($permalink_manager_uris[$post->ID]);
404
+ }
405
+ // Save only changed URIs
406
+ else if (($new_uri != $native_uri) && ($new_uri != $old_uri)) {
407
+ $permalink_manager_uris[$post->ID] = $new_uri;
408
+ }
409
+
410
+ update_option('permalink-manager-uris', $permalink_manager_uris);
411
+ }
412
+
413
+ /**
414
+ * Remove URI from options array after post is moved to the trash
415
+ */
416
+ function remove_post_uri($post_id) {
417
+ global $permalink_manager_uris;
418
+
419
+ // Check if the custom permalink is assigned to this post
420
+ if(isset($permalink_manager_uris[$post_id])) {
421
+ unset($permalink_manager_uris[$post_id]);
422
+ }
423
+
424
+ update_option('permalink-manager-uris', $permalink_manager_uris);
425
+ }
426
+
427
+ /**
428
+ * Remove URI from options array after post is moved to the trash
429
+ */
430
+ function clear_uris($post_id) {
431
+ $uris = $this->permalink_manager_uris;
432
+
433
+ foreach($uris as $post_id => $uri) {
434
+ $post_status = get_post_status($post_id);
435
+ if(in_array($post_status, array('auto-draft', 'trash', ''))) {
436
+ unset($uris[$post_id]);
437
+ }
438
+ }
439
+
440
+ update_option('permalink-manager-uris', $uris);
441
+ }
442
+
443
+ }
444
+
445
+ ?>
includes/core/permalink-manager-uri-actions.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Register all action hooks
5
+ */
6
+ class Permalink_Manager_Uri_Actions extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_action('admin_init', array($this, 'trigger_action'), 0);
10
+
11
+ add_action( 'save_post', array($this, 'update_single_uri'), 10, 3 );
12
+ add_action( 'wp_trash_post', array($this, 'remove_single_uri'), 10, 3 );
13
+ }
14
+
15
+ /**
16
+ * Trigger the specific action
17
+ */
18
+ function trigger_action() {
19
+ global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
20
+
21
+ // Triggered in "Permalink Editor" section
22
+ if(isset($_POST['slug_editor']) && wp_verify_nonce($_POST['slug_editor'], 'uri_actions')) {
23
+ $updated_list = $this->posts_update_all_permalinks();
24
+
25
+ $updated_slugs_count = (isset($updated_list['updated_count']) && $updated_list['updated_count'] > 0) ? $updated_list['updated_count'] : false;
26
+ $updated_slugs_array = ($updated_slugs_count) ? $updated_list['updated'] : '';
27
+ }
28
+ // Triggered in "Regenerate/Rest" section
29
+ else if(isset($_POST['regenerate_posts']) && wp_verify_nonce($_POST['regenerate_posts'], 'uri_actions')) {
30
+ $updated_list = $this->posts_regenerate_all_permalinks();
31
+
32
+ $updated_slugs_count = (isset($updated_list['updated_count']) && $updated_list['updated_count'] > 0) ? $updated_list['updated_count'] : false;
33
+ $updated_slugs_array = ($updated_slugs_count) ? $updated_list['updated'] : '';
34
+ }
35
+ // Triggered in "Find and Replace" section
36
+ else if(isset($_POST['find_and_replace']) && wp_verify_nonce($_POST['find_and_replace'], 'uri_actions')) {
37
+ $updated_list = $this->posts_find_and_replace();
38
+
39
+ $updated_slugs_count = (isset($updated_list['updated_count']) && $updated_list['updated_count'] > 0) ? $updated_list['updated_count'] : false;
40
+ $updated_slugs_array = ($updated_slugs_count) ? $updated_list['updated'] : '';
41
+ }
42
+
43
+ // 2. Display the slugs table (and append the globals)
44
+ if(isset($updated_slugs_count)) {
45
+ if($updated_slugs_count > 0) {
46
+ $alert_content = sprintf( _n( '<strong>%d</strong> slug was updated!', '<strong>%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
47
+ $alert_content .= sprintf( __( '<a href="%s">Click here</a> to go to the list of updated slugs', 'permalink-manager' ), '#updated-list');
48
+
49
+ $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message($alert_content, 'updated');
50
+ $permalink_manager_after_sections_html .= Permalink_Manager_Admin_Functions::display_updated_slugs($updated_slugs_array);
51
+ } else {
52
+ $alert_content = __( '<strong>No slugs</strong> were updated!', 'permalink-manager' );
53
+ $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message($alert_content, 'error');
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Find & replace (bulk action)
60
+ */
61
+ static function posts_find_and_replace() {
62
+ global $wpdb, $permalink_manager_uris;
63
+
64
+ // Reset variables
65
+ $updated_slugs_count = 0;
66
+ $updated_array = array();
67
+ $alert_type = $alert_content = $errors = '';
68
+
69
+ // Prepare default variables from $_POST object
70
+ $old_string = esc_sql($_POST['old_string']);
71
+ $new_string = esc_sql($_POST['new_string']);
72
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : array('both');
73
+ $post_types_array = ($_POST['post_types']);
74
+ $post_statuses_array = ($_POST['post_statuses']);
75
+ $post_types = implode("', '", $post_types_array);
76
+ $post_statuses = implode("', '", $post_statuses_array);
77
+
78
+ // Save the rows before they are updated to an array
79
+ $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
80
+
81
+ // Now if the array is not empty use IDs from each subarray as a key
82
+ if($posts_to_update && empty($errors)) {
83
+ foreach ($posts_to_update as $row) {
84
+
85
+ // Prepare variables
86
+ $old_post_name = $row['post_name'];
87
+ $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($row['ID'], true);
88
+ $default_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($row['ID']);
89
+ $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $default_uri;
90
+ $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
91
+ $old_base = (strpos($old_uri, '/') !== false) ? substr($old_uri, 0, strrpos( $old_uri, '/') ) : '';
92
+
93
+ // Process URI & slug
94
+ $new_slug = str_replace($old_string, $new_string, $old_slug);
95
+ $new_base = str_replace($old_string, $new_string, $old_base);
96
+ $new_uri = (in_array($mode, array('both'))) ? trim("{$new_base}/{$new_slug}", "/") : trim("{$old_base}/{$new_slug}", "/");
97
+ $new_post_name = (in_array($mode, array('post_names'))) ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
98
+
99
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
100
+
101
+ // Check if native slug should be changed
102
+ if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
103
+ Permalink_Manager_Post_URI_Functions::update_slug_by_id($new_post_name, $row['ID']);
104
+ }
105
+
106
+ if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
107
+ $permalink_manager_uris[$row['ID']] = $new_uri;
108
+ $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
109
+ $updated_slugs_count++;
110
+ }
111
+
112
+ // Do not store default values
113
+ if(isset($permalink_manager_uris[$row['ID']]) && ($new_uri == $native_uri)) {
114
+ unset($permalink_manager_uris[$row['ID']]);
115
+ }
116
+ }
117
+
118
+ // Filter array before saving
119
+ $permalink_manager_uris = array_filter($permalink_manager_uris);
120
+ update_option('permalink-manager-uris', $permalink_manager_uris);
121
+
122
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
123
+ wp_reset_postdata();
124
+ }
125
+
126
+ return ($output) ? $output : "";
127
+ }
128
+
129
+ /**
130
+ * Regenerate slugs & bases (bulk action)
131
+ */
132
+ static function posts_regenerate_all_permalinks() {
133
+ global $wpdb, $permalink_manager_uris, $permalink_manager_permastructs;
134
+
135
+ // Setup needed variables
136
+ $updated_slugs_count = 0;
137
+ $updated_array = array();
138
+ $alert_type = $alert_content = $errors = '';
139
+
140
+ // Check if post types & statuses are not empty
141
+ if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
142
+
143
+ $post_types_array = ($_POST['post_types']) ? ($_POST['post_types']) : '';
144
+ $post_statuses_array = ($_POST['post_statuses']) ? $_POST['post_statuses'] : '';
145
+ $post_types = implode("', '", $post_types_array);
146
+ $post_statuses = implode("', '", $post_statuses_array);
147
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : 'both';
148
+
149
+ // Save the rows before they are updated to an array
150
+ $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, post_type, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
151
+
152
+ // Now if the array is not empty use IDs from each subarray as a key
153
+ if($posts_to_update && empty($errors)) {
154
+ foreach ($posts_to_update as $row) {
155
+ $updated = 0;
156
+
157
+ // Prepare variables
158
+ $old_post_name = $row['post_name'];
159
+ $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($row['ID'], true);
160
+ $default_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($row['ID']);
161
+ $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
162
+ $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
163
+ $correct_slug = sanitize_title($row['post_title']);
164
+
165
+ // Process URI & slug
166
+ $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
167
+ $new_post_name = (in_array($mode, array('post_names'))) ? $new_slug : $old_post_name; // Post name is changed only in first mode
168
+ $new_uri = (in_array($mode, array('both'))) ? $default_uri : str_replace($old_slug, $new_slug, $old_uri);
169
+
170
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
171
+
172
+ // Check if native slug should be changed
173
+ if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
174
+ Permalink_Manager_Post_URI_Functions::update_slug_by_id($new_post_name, $row['ID']);
175
+ }
176
+
177
+ if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
178
+ $permalink_manager_uris[$row['ID']] = $new_uri;
179
+ $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
180
+ $updated_slugs_count++;
181
+ }
182
+
183
+ // Do not store default values
184
+ if(isset($permalink_manager_uris[$row['ID']]) && ($new_uri == $native_uri)) {
185
+ unset($permalink_manager_uris[$row['ID']]);
186
+ }
187
+ }
188
+
189
+ // Filter array before saving
190
+ $permalink_manager_uris = array_filter($permalink_manager_uris);
191
+ update_option('permalink-manager-uris', $permalink_manager_uris);
192
+
193
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
194
+ wp_reset_postdata();
195
+ }
196
+
197
+ return (!empty($output)) ? $output : "";
198
+ }
199
+
200
+ /**
201
+ * Update all slugs & bases (bulk action)
202
+ */
203
+ public function posts_update_all_permalinks() {
204
+ global $permalink_manager_uris;
205
+
206
+ // Setup needed variables
207
+ $updated_slugs_count = 0;
208
+ $updated_array = array();
209
+
210
+ $old_uris = $permalink_manager_uris;
211
+ $new_uris = isset($_POST['uri']) ? $_POST['uri'] : array();
212
+
213
+ // Double check if the slugs and ids are stored in arrays
214
+ if (!is_array($new_uris)) $new_uris = explode(',', $new_uris);
215
+
216
+ if (!empty($new_uris)) {
217
+ foreach($new_uris as $id => $new_uri) {
218
+ // Prepare variables
219
+ $this_post = get_post($id);
220
+ $updated = '';
221
+
222
+ // Get default & native URL
223
+ $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($id, true);
224
+ $default_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($id);
225
+
226
+ $old_uri = isset($old_uris[$id]) ? trim($old_uris[$id], "/") : $native_uri;
227
+
228
+ // Process new values - empty entries will be treated as default values
229
+ $new_uri = preg_replace('/\s+/', '', $new_uri);
230
+ $new_uri = (!empty($new_uri)) ? trim($new_uri, "/") : $default_uri;
231
+ $new_slug = (strpos($new_uri, '/') !== false) ? substr($new_uri, strrpos($new_uri, '/') + 1) : $new_uri;
232
+
233
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
234
+
235
+ // Do not store native URIs
236
+ if($new_uri == $native_uri) {
237
+ unset($old_uris[$id]);
238
+ }
239
+
240
+ if($new_uri != $old_uri) {
241
+ $old_uris[$id] = $new_uri;
242
+ $updated_array[] = array('post_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
243
+ $updated_slugs_count++;
244
+ }
245
+
246
+ }
247
+
248
+ // Filter array before saving & append the global
249
+ $old_uris = $permalink_manager_uris = array_filter($old_uris);
250
+ update_option('permalink-manager-uris', $old_uris);
251
+
252
+ $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
253
+ }
254
+
255
+ return ($output) ? $output : "";
256
+ }
257
+
258
+ /**
259
+ * Remove URI from options array after post is moved to the trash
260
+ */
261
+ function clear_uris($post_id) {
262
+ $uris = $this->permalink_manager_uris;
263
+
264
+ foreach($uris as $post_id => $uri) {
265
+ $post_status = get_post_status($post_id);
266
+ if(in_array($post_status, array('auto-draft', 'trash', ''))) {
267
+ unset($uris[$post_id]);
268
+ }
269
+ }
270
+
271
+ update_option('permalink-manager-uris', $uris);
272
+ }
273
+
274
+ /**
275
+ * Update permastructs
276
+ */
277
+ static function update_permastructs() {
278
+ // Setup needed variables
279
+ $alert_type = $alert_content = $errors = '';
280
+ $permastructs = get_option('permalink-manager-permastructs', array());
281
+ $new_permastructs = array_filter($_POST['permalink-manager']['custom-permastructs']);
282
+
283
+ foreach($new_permastructs as $post_type => $new_permstruct) {
284
+ $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type, true);
285
+ $permastructs[$post_type] = trim(preg_replace('/\s+/', '', $new_permstruct), "/");
286
+
287
+ // Do not save default permastructs
288
+ if($default_permastruct == $new_permstruct) {
289
+ unset($permastructs[$post_type]);
290
+ }
291
+ }
292
+
293
+ update_option('permalink-manager-permastructs', $permastructs);
294
+
295
+ return "";
296
+ }
297
+
298
+ /**
299
+ * Update URI from "Edit Post" admin page
300
+ */
301
+ function update_single_uri($post_id, $post, $update) {
302
+ global $permalink_manager_uris;
303
+
304
+ // Ignore trashed items
305
+ if($post->post_status == 'trash') return;
306
+
307
+ // Fix for revisions
308
+ $is_revision = wp_is_post_revision($post_id);
309
+ $post_id = ($is_revision) ? $is_revision : $post_id;
310
+ $post = get_post($post_id);
311
+
312
+ $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($post, true);
313
+ $old_uri = (isset($permalink_manager_uris[$post->ID])) ? $permalink_manager_uris[$post->ID] : $native_uri;
314
+ $new_uri = '';
315
+
316
+ // Check if user changed URI (available after post is saved)
317
+ if(isset($_POST['custom_uri'])) {
318
+ $new_uri = trim($_POST['custom_uri'], "/");
319
+ }
320
+
321
+ // A little hack (if user removes whole URI from input) ...
322
+ $new_uri = ($new_uri) ? $new_uri : Permalink_Manager_Post_URI_Functions::get_post_uri($post);
323
+
324
+ // Do not store default values
325
+ if(isset($permalink_manager_uris[$post->ID]) && ($new_uri == $native_uri)) {
326
+ unset($permalink_manager_uris[$post->ID]);
327
+ }
328
+ // Save only changed URIs
329
+ else if (($new_uri != $native_uri) && ($new_uri != $old_uri)) {
330
+ $permalink_manager_uris[$post->ID] = $new_uri;
331
+ }
332
+
333
+ update_option('permalink-manager-uris', $permalink_manager_uris);
334
+ }
335
+
336
+ /**
337
+ * Remove URI from options array after post is moved to the trash
338
+ */
339
+ function remove_single_uri($post_id) {
340
+ global $permalink_manager_uris;
341
+
342
+ // Check if the custom permalink is assigned to this post
343
+ if(isset($permalink_manager_uris[$post_id])) {
344
+ unset($permalink_manager_uris[$post_id]);
345
+ }
346
+
347
+ update_option('permalink-manager-uris', $permalink_manager_uris);
348
+ }
349
+
350
+ }
includes/views/permalink-manager-advanced.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Display the page where the slugs could be regenerated or replaced
5
+ */
6
+ class Permalink_Manager_Advanced extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_advanced_section'), 1 );
10
+ }
11
+
12
+ public function add_advanced_section($admin_sections) {
13
+ $admin_sections['advanced'] = array(
14
+ 'name' => __('Advanced', 'permalink-manager'),
15
+ 'function' => array('class' => 'Permalink_Manager_Advanced', 'method' => 'output')
16
+ );
17
+
18
+ return $admin_sections;
19
+ }
20
+
21
+ public function output() {
22
+ global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_filter;
23
+
24
+ // Get permalink hooks
25
+ foreach(array('_get_page_link', 'post_link', 'page_link', 'post_type_link') as $hook) {
26
+ $permalink_hooks[$hook] = json_encode($wp_filter[$hook]);
27
+ }
28
+
29
+ $sections_and_fields = apply_filters('permalink-manager-settings-fields', array(
30
+ 'debug-data' => array(
31
+ 'section_name' => __('Debug data', 'permalink-manager'),
32
+ 'fields' => array(
33
+ 'uris' => array(
34
+ 'type' => 'textarea',
35
+ 'description' => __('List of the URIs generated by this plugin.', 'permalink-manager'),
36
+ 'label' => __('Array with URIs', 'permalink-manager'),
37
+ 'input_class' => 'short-textarea widefat',
38
+ 'value' => ($permalink_manager_uris) ? print_r($permalink_manager_uris, true) : ''
39
+ ),
40
+ 'permastructs' => array(
41
+ 'type' => 'textarea',
42
+ 'description' => __('List of the permastructures.', 'permalink-manager'),
43
+ 'label' => __('Array with permastructures', 'permalink-manager'),
44
+ 'input_class' => 'short-textarea widefat',
45
+ 'value' => ($permalink_manager_permastructs) ? print_r($permalink_manager_permastructs, true) : ''
46
+ ),
47
+ 'settings' => array(
48
+ 'type' => 'textarea',
49
+ 'description' => __('Currently used plugin settings.', 'permalink-manager'),
50
+ 'label' => __('Array with settings used in this plugin.', 'permalink-manager'),
51
+ 'input_class' => 'short-textarea widefat',
52
+ 'value' => print_r($permalink_manager_options, true)
53
+ ),
54
+ 'hooks' => array(
55
+ 'type' => 'textarea',
56
+ 'description' => __('Permalink hooks.', 'permalink-manager'),
57
+ 'label' => __('Array with list of permalink hooks used on this website.', 'permalink-manager'),
58
+ 'input_class' => 'short-textarea widefat',
59
+ 'value' => print_r($permalink_hooks, true)
60
+ )
61
+ )
62
+ )
63
+ ));
64
+
65
+ // Now get the HTML output
66
+ $output = '';
67
+ foreach($sections_and_fields as $section_id => $section) {
68
+ $output .= "<h4>{$section['section_name']}</h4>";
69
+ $output .= (isset($section['description'])) ? "<p class=\"description\">{$section['description']}</p>" : "";
70
+ $output .= "<table class=\"form-table fixed-table\">";
71
+
72
+ // Loop through all fields assigned to this section
73
+ foreach($section['fields'] as $field_id => $field) {
74
+ $field_name = "{$section_id}[$field_id]";
75
+ $field['container'] = 'row';
76
+
77
+ $output .= Permalink_Manager_Admin_Functions::generate_option_field($field_name, $field);
78
+ }
79
+
80
+ // End the section
81
+ $output .= "</table>";
82
+
83
+ }
84
+
85
+ return $output;
86
+ }
87
+
88
+ }
includes/views/permalink-manager-permastructs.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Display the page where the slugs could be regenerated or replaced
5
+ */
6
+ class Permalink_Manager_Permastructs extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
10
+ }
11
+
12
+ public function add_admin_section($admin_sections) {
13
+
14
+ $admin_sections['permastructs'] = array(
15
+ 'name' => __('Permastructures', 'permalink-manager'),
16
+ 'function' => array('class' => 'Permalink_Manager_Permastructs', 'method' => 'output')
17
+ );
18
+
19
+ return $admin_sections;
20
+ }
21
+
22
+ /**
23
+ * Get the array with settings and render the HTML output
24
+ */
25
+ public function output() {
26
+ global $permalink_manager_permastructs;
27
+
28
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array('full');
29
+ $fields = array();
30
+
31
+ // 2. Get all post types
32
+ foreach($all_post_types as $post_type) {
33
+
34
+ $default_permastruct = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type['name'], true);
35
+ $current_permastruct = isset($permalink_manager_permastructs[$post_type['name']]) ? $permalink_manager_permastructs[$post_type['name']] : '';
36
+
37
+ $fields["permastructures[{$post_type['name']}]"] = array(
38
+ 'label' => $post_type['label'],
39
+ 'container' => 'row',
40
+ 'input_class' => 'widefat',
41
+ 'value' => $current_permastruct,
42
+ 'placeholder' => $default_permastruct,
43
+ 'type' => 'text'
44
+ );
45
+ }
46
+
47
+ // 2. Display some notes
48
+ $notes[] = sprintf( __('All available <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() . "\n";
49
+ $notes[] = __('Each Custom Post Type should have unique permastructure.', 'permalink-manager');
50
+ $notes[] = __('Please note that the following settings will be applied only to new posts.<br />If you would like to use the current permastructures settings, you will need to regenerate the posts\' URIs in <strong>"Tools -> Regnerate/Reset"</strong> section.', 'permalink-manager');
51
+ $notes[] = __('To use the native permastruct please keep the field empty.', 'permalink-manager');
52
+ $sidebar = '<h3>' . __('Usage Instructions', 'permalink-manager') . '</h3>';
53
+ $sidebar .= "<ol><li>" . implode('</li><li>', $notes) . "</li></ol>";
54
+
55
+ $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Save permastructures', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'save_settings', 'name' => 'permalink-manager-permastructs'));
56
+ return $output;
57
+ }
58
+
59
+ }
includes/views/permalink-manager-settings.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Display the settings page
5
+ */
6
+ class Permalink_Manager_Settings extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
10
+ add_filter( 'permalink-manager-options', array($this, 'default_settings'), 9 );
11
+ }
12
+
13
+ public function add_admin_section($admin_sections) {
14
+ $admin_sections['settings'] = array(
15
+ 'name' => __('Settings', 'permalink-manager'),
16
+ 'function' => array('class' => 'Permalink_Manager_Settings', 'method' => 'output')
17
+ );
18
+
19
+ return $admin_sections;
20
+ }
21
+
22
+ /**
23
+ * Set the initial/default settings
24
+ */
25
+ public function default_settings($settings) {
26
+ $default_settings = apply_filters('permalink-manager-default-options', array(
27
+ 'screen-options' => array(
28
+ 'per_page' => 20,
29
+ 'post_statuses' => array('publish'),
30
+ 'post_types' => array('page', 'post')
31
+ ),
32
+ 'miscellaneous' => array(
33
+ 'yoast_primary_term' => 1,
34
+ 'redirect' => "302",
35
+ 'canonical_redirect' => 1,
36
+ )
37
+ ));
38
+
39
+ // Apply the default settings (if empty values) in all settings sections
40
+ $final_settings = array();
41
+ foreach($default_settings as $section => $fields) {
42
+ $final_settings[$section] = (isset($settings[$section])) ? array_replace($fields, $settings[$section]) : $fields;
43
+ }
44
+
45
+ return $final_settings;
46
+ }
47
+
48
+ /**
49
+ * Get the array with settings and render the HTML output
50
+ */
51
+ public function output() {
52
+ // Get all registered post types array & statuses
53
+ $all_post_statuses_array = get_post_statuses();
54
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
55
+
56
+ $sections_and_fields = apply_filters('permalink-manager-settings-fields', array(
57
+ 'screen-options' => array(
58
+ 'section_name' => __('Display settings', 'permalink-manager'),
59
+ 'description' => __('Adjust the data displayed in "Permalink Editor" section.', 'permalink-manager'),
60
+ 'fields' => array(
61
+ 'per_page' => array(
62
+ 'type' => 'number',
63
+ 'label' => __('Per page', 'permalink-manager'),
64
+ 'input_class' => 'settings-select'
65
+ ),
66
+ 'post_statuses' => array(
67
+ 'type' => 'checkbox',
68
+ 'label' => __('Post statuses', 'permalink-manager'),
69
+ 'choices' => $all_post_statuses_array,
70
+ 'select_all' => '',
71
+ 'unselect_all' => '',
72
+ ),
73
+ 'post_types' => array(
74
+ 'type' => 'checkbox',
75
+ 'label' => __('Post types', 'permalink-manager'),
76
+ 'choices' => $all_post_types,
77
+ 'select_all' => '',
78
+ 'unselect_all' => '',
79
+ ),
80
+ )
81
+ ),
82
+ 'miscellaneous' => array(
83
+ 'section_name' => __('Miscellaneous & SEO functions', 'permalink-manager'),
84
+ 'fields' => array(
85
+ 'yoast_primary_term' => array(
86
+ 'type' => 'select',
87
+ 'label' => __('Primay term/category support', 'permalink-manager'),
88
+ 'input_class' => 'settings-select',
89
+ 'choices' => array(1 => __('Enable', 'permalink-manager'), 0 => __('Disable', 'permalink-manager')),
90
+ 'description' => __('Used to generate default permalinks in pages, posts & custom post types. Works only when "Yoast SEO" plugin is enabled.', 'permalink-manager')
91
+ ),
92
+ 'redirect' => array(
93
+ 'type' => 'select',
94
+ 'label' => __('Redirect', 'permalink-manager'),
95
+ 'input_class' => 'settings-select',
96
+ 'choices' => array(0 => __('Disable', 'permalink-manager'), "301" => __('Enable "301 redirect"', 'permalink-manager'), "302" => __('Enable "302 redirect"', 'permalink-manager')),
97
+ 'description' => __('If enabled - the visitors will be redirected from native permalinks to your custom permalinks. Please note that the redirects will work correctly only if native slug "post name" will not be changed.', 'permalink-manager')
98
+ ),
99
+ 'canonical_redirect' => array(
100
+ 'type' => 'select',
101
+ 'label' => __('Canonical redirect', 'permalink-manager'),
102
+ 'input_class' => 'settings-select',
103
+ 'choices' => array(0 => __('Disable', 'permalink-manager'), 1 => __('Enable', 'permalink-manager')),
104
+ 'description' => __('This function allows Wordpress to correct the URLs used by the visitors.', 'permalink-manager')
105
+ )
106
+ )
107
+ )
108
+ ));
109
+
110
+ $output = Permalink_Manager_Admin_Functions::get_the_form($sections_and_fields, '', array('text' => __( 'Save settings', 'permalink-manager' ), 'class' => 'primary margin-top'), '', array('action' => 'save_settings', 'name' => 'permalink-manager-options'));
111
+ return $output;
112
+ }
113
+
114
+ }
includes/views/permalink-manager-tools.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Display the page where the slugs could be regenerated or replaced
5
+ */
6
+ class Permalink_Manager_Tools extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
10
+ }
11
+
12
+ public function add_admin_section($admin_sections) {
13
+
14
+ $admin_sections['tools'] = array(
15
+ 'name' => __('Tools', 'permalink-manager'),
16
+ 'subsections' => array(
17
+ 'find_and_replace' => array(
18
+ 'name' => __('Find and replace', 'permalink-manager'),
19
+ 'function' => array('class' => 'Permalink_Manager_Tools', 'method' => 'find_and_replace_output')
20
+ ),
21
+ 'regenerate_slugs' => array(
22
+ 'name' => __('Regenerate/Reset', 'permalink-manager'),
23
+ 'function' => array('class' => 'Permalink_Manager_Tools', 'method' => 'regenerate_slugs_output')
24
+ )
25
+ )
26
+ );
27
+
28
+ return $admin_sections;
29
+ }
30
+
31
+ public function display_instructions() {
32
+ $output = wpautop(sprintf(__('<h4>A MySQL backup is highly recommended before using "<em>Custom & native slugs (post names)</em>" mode!</h4>With this mode selected, <strong>post_name</strong> field (native slug) will be changed directly in <a href="%s"><strong>"posts"</strong></a> database table.', 'permalink-manager'), 'https://codex.wordpress.org/Database_Description#Table:_wp_posts'));
33
+ return $output;
34
+ }
35
+
36
+ public function find_and_replace_output() {
37
+ // Get all registered post types array & statuses
38
+ $all_post_statuses_array = get_post_statuses();
39
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
40
+
41
+ $fields = array(
42
+ array('group' => array(
43
+ 'old_string' => array(
44
+ 'label' => __( 'Find ...', 'permalink-manager' ),
45
+ 'type' => 'text',
46
+ 'container_class' => 'column column-1_2',
47
+ 'input_class' => 'widefat'
48
+ ),
49
+ 'new_string' => array(
50
+ 'label' => __( 'Replace with ...', 'permalink-manager' ),
51
+ 'type' => 'text',
52
+ 'container_class' => 'column column-1_2',
53
+ 'input_class' => 'widefat'
54
+ ),
55
+ )),
56
+ 'mode' => array(
57
+ 'label' => __( 'Select mode', 'permalink-manager' ),
58
+ 'type' => 'select',
59
+ 'choices' => array('both' => '<strong>' . __('Full URIs', 'permalink-manager') . '</strong>', 'slugs' => '<strong>' . __('Only custom slugs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Custom & native slugs (post names)', 'permalink-manager') . '</strong>'),
60
+ 'default' => array('both'),
61
+ ),
62
+ 'post_types' => array(
63
+ 'label' => __( 'Filter by post types', 'permalink-manager' ),
64
+ 'type' => 'checkbox',
65
+ 'default' => array('post', 'page'),
66
+ 'choices' => $all_post_types,
67
+ 'select_all' => '',
68
+ 'unselect_all' => '',
69
+ ),
70
+ 'post_statuses' => array(
71
+ 'label' => __( 'Filter by post statuses', 'permalink-manager' ),
72
+ 'type' => 'checkbox',
73
+ 'default' => array('publish'),
74
+ 'choices' => $all_post_statuses_array,
75
+ 'select_all' => '',
76
+ 'unselect_all' => '',
77
+ )
78
+ );
79
+
80
+ $sidebar = '<h3>' . __('Important notes', 'permalink-manager') . '</h3>';
81
+ $sidebar .= self::display_instructions();
82
+
83
+ $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Find and replace', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'uri_actions', 'name' => 'find_and_replace'));
84
+
85
+ return $output;
86
+ }
87
+
88
+ public function regenerate_slugs_output() {
89
+ // Get all registered post types array & statuses
90
+ $all_post_statuses_array = get_post_statuses();
91
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
92
+
93
+ $fields = array(
94
+ 'mode' => array(
95
+ 'label' => __( 'Select mode', 'permalink-manager' ),
96
+ 'type' => 'select',
97
+ 'choices' => array('both' => '<strong>' . __('Full URIs', 'permalink-manager') . '</strong>', 'slugs' => '<strong>' . __('Only custom slugs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Custom & native slugs (post names)', 'permalink-manager') . '</strong>'),
98
+ ),
99
+ 'post_types' => array(
100
+ 'label' => __( 'Filter by post types', 'permalink-manager' ),
101
+ 'type' => 'checkbox',
102
+ 'default' => array('post', 'page'),
103
+ 'choices' => $all_post_types,
104
+ 'select_all' => '',
105
+ 'unselect_all' => '',
106
+ ),
107
+ 'post_statuses' => array(
108
+ 'label' => __( 'Filter by post statuses', 'permalink-manager' ),
109
+ 'type' => 'checkbox',
110
+ 'default' => array('publish'),
111
+ 'choices' => $all_post_statuses_array,
112
+ 'select_all' => '',
113
+ 'unselect_all' => '',
114
+ )
115
+ );
116
+
117
+ $sidebar = '<h3>' . __('Important notes', 'permalink-manager') . '</h3>';
118
+ $sidebar .= self::display_instructions();
119
+ $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Regenerate', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'uri_actions', 'name' => 'regenerate_posts'));
120
+
121
+ return $output;
122
+ }
123
+
124
+ }
includes/views/permalink-manager-uri-editor.php ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Display slug editor for Posts, Pages & Custom Post Types
5
+ */
6
+ class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
10
+ }
11
+
12
+ /**
13
+ * Add the section to the Permalink Manager admin page
14
+ */
15
+ public function add_admin_section($admin_sections) {
16
+ global $permalink_manager_options;
17
+
18
+ $admin_sections['slug_editor'] = array(
19
+ 'name' => __('Permalink editor', 'permalink-manager'),
20
+ 'function' => array('class' => 'Permalink_Manager_Uri_Editor_Table', 'method' => 'display_admin_section')
21
+ );
22
+
23
+ // Display separate section for each post type
24
+ $post_types = Permalink_Manager_Helper_Functions::get_post_types_array('full');
25
+ foreach($permalink_manager_options['screen-options']['post_types'] as $post_type) {
26
+ $admin_sections['slug_editor']['subsections'][$post_type] = array(
27
+ 'name' => $post_types[$post_type]['label']
28
+ );
29
+ }
30
+
31
+ return $admin_sections;
32
+ }
33
+
34
+ }
35
+
36
+ class Permalink_Manager_Uri_Editor_Table extends WP_List_Table {
37
+
38
+ public function __construct() {
39
+ global $status, $page;
40
+
41
+ parent::__construct(array(
42
+ 'singular' => 'slug',
43
+ 'plural' => 'slugs'
44
+ ));
45
+ }
46
+
47
+ /**
48
+ * Get the HTML output with the WP_List_Table
49
+ */
50
+ public function display_admin_section() {
51
+ global $wpdb;
52
+
53
+ $output = "<form id=\"permalinks-post-types-table\" class=\"slugs-table\" method=\"post\">";
54
+ $output .= wp_nonce_field('uri_actions', 'slug_editor', true, true);
55
+
56
+ // Bypass
57
+ ob_start();
58
+
59
+ $this->prepare_items();
60
+ $this->display();
61
+ $output .= ob_get_contents();
62
+
63
+ ob_end_clean();
64
+
65
+ $output .= "</form>";
66
+
67
+ return $output;
68
+ }
69
+
70
+ /**
71
+ * Override the parent columns method. Defines the columns to use in your listing table
72
+ */
73
+ public function get_columns() {
74
+ $columns = array(
75
+ //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
76
+ 'post_title' => __('Post title', 'permalink-manager'),
77
+ 'post_name' => __('Post name (native slug)', 'permalink-manager'),
78
+ //'post_date_gmt' => __('Date', 'permalink-manager'),
79
+ 'uri' => __('Full URI & Permalink', 'permalink-manager'),
80
+ 'post_status' => __('Post status', 'permalink-manager'),
81
+ );
82
+
83
+ return $columns;
84
+ }
85
+
86
+ /**
87
+ * Hidden columns
88
+ */
89
+ public function get_hidden_columns() {
90
+ return array('post_date_gmt');
91
+ }
92
+
93
+ /**
94
+ * Sortable columns
95
+ */
96
+ public function get_sortable_columns() {
97
+ return array(
98
+ 'post_title' => array('post_title', false),
99
+ 'post_name' => array('post_name', false),
100
+ 'post_status' => array('post_status', false),
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Data inside the columns
106
+ */
107
+ public function column_default( $item, $column_name ) {
108
+
109
+ $base = Permalink_Manager_Post_URI_Functions::get_post_uri($item[ 'ID' ], false, false);
110
+ $field_args_base = array('type' => 'text', 'value' => $base, 'without_label' => true, 'input_class' => '');
111
+ $permalink = Permalink_Manager_Post_URI_Functions::get_correct_permalink($item['ID']);
112
+
113
+ switch( $column_name ) {
114
+ case 'post_status':
115
+ $post_statuses_array = get_post_statuses();
116
+ return "<span title=\"{$item[$column_name]}\">{$post_statuses_array[$item[$column_name]]}</span>";
117
+
118
+ case 'post_name':
119
+ $output = $item[ 'post_name' ];
120
+ return $output;
121
+
122
+ case 'uri':
123
+ $output = ($item['post_status'] != 'publish') ? '-' : Permalink_Manager_Admin_Functions::generate_option_field("uri[{$item['ID']}]", $field_args_base);
124
+ $output .= "<a class=\"small post_permalink\" href=\"{$permalink}\" target=\"_blank\"><span class=\"dashicons dashicons-admin-links\"></span> {$permalink}</a>";
125
+ return $output;;
126
+
127
+ case 'post_title':
128
+ $output = $item[ 'post_title' ];
129
+ $output .= '<div class="row-actions">';
130
+ $output .= '<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>';
131
+ $output .= '<span class="view"><a target="_blank" href="' . $permalink . '" title="' . __('View', 'permalink-manager') . ' ' . $item[ 'post_title' ] . '" rel="permalink">' . __('View', 'permalink-manager') . '</a> | </span>';
132
+ $output .= '<span class="id">#' . $item[ 'ID' ] . '</span>';
133
+ $output .= '</div>';
134
+ return $output;
135
+
136
+ default:
137
+ return $item[ $column_name ];
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Sort the data
143
+ */
144
+ private function sort_data( $a, $b ) {
145
+ // Set defaults
146
+ $orderby = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'post_title';
147
+ $order = (!empty($_GET['order'])) ? $_GET['order'] : 'asc';
148
+ $result = strnatcasecmp( $a[$orderby], $b[$orderby] );
149
+
150
+ return ($order === 'asc') ? $result : -$result;
151
+ }
152
+
153
+ /**
154
+ * The button that allows to save updated slugs
155
+ */
156
+ function extra_tablenav( $which ) {
157
+ $button_top = __( 'Update all the URIs below', 'permalink-manager' );
158
+ $button_bottom = __( 'Update all the URIs above', 'permalink-manager' );
159
+
160
+ echo '<div class="alignleft actions">';
161
+ submit_button( ${"button_$which"}, 'primary', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
162
+ echo '</div>';
163
+ }
164
+
165
+ /**
166
+ * Prepare the items for the table to process
167
+ */
168
+ public function prepare_items() {
169
+ global $wpdb, $permalink_manager_options, $active_subsection;
170
+
171
+ $columns = $this->get_columns();
172
+ $hidden = $this->get_hidden_columns();
173
+ $sortable = $this->get_sortable_columns();
174
+ $current_page = $this->get_pagenum();
175
+
176
+ // Get query variables
177
+ $per_page = $permalink_manager_options['screen-options']['per_page'];
178
+ $post_types_array = $permalink_manager_options['screen-options']['post_types'];
179
+ $post_types = ($active_subsection && $active_subsection != 'all') ? "'{$active_subsection}'" : "'" . implode("', '", $post_types_array) . "'";
180
+ $post_statuses_array = $permalink_manager_options['screen-options']['post_statuses'];;
181
+ $post_statuses = "'" . implode("', '", $post_statuses_array) . "'";
182
+
183
+ // Will be used in pagination settings
184
+ $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types)");
185
+
186
+ // SQL query parameters
187
+ $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
188
+ $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
189
+ $offset = ($current_page - 1) * $per_page;
190
+
191
+ // Grab posts from database
192
+ //$sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order LIMIT $per_page OFFSET $offset";
193
+ $sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order";
194
+ $all_data = $wpdb->get_results($sql_query, ARRAY_A);
195
+
196
+ // Sort posts and count all posts
197
+ usort( $all_data, array( &$this, 'sort_data' ) );
198
+
199
+ $data = array_slice($all_data, $offset, $per_page);
200
+
201
+ // Debug SQL query
202
+ $debug_txt = "<textarea style=\"width:100%;height:300px\">{$sql_query} \n\nOffset: {$offset} \nPage: {$current_page}\nPer page: {$per_page} \nTotal: {$total_items}</textarea>";
203
+ if(isset($_REQUEST['debug_editor_sql'])) { wp_die($debug_txt); }
204
+
205
+ $this->set_pagination_args( array(
206
+ 'total_items' => $total_items,
207
+ 'per_page' => $per_page
208
+ ));
209
+
210
+ $this->_column_headers = array($columns, $hidden, $sortable);
211
+ $this->items = $data;
212
+ }
213
+
214
+ }
languages/permalink-manager.pot CHANGED
@@ -1,216 +1,397 @@
1
- # Loco Gettext template
2
- #, fuzzy
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Permalink Manager\n"
6
- "Report-Msgid-Bugs-To: \n"
7
- "POT-Creation-Date: Fri Jan 08 2016 20:08:17 GMT+0100 (CET)\n"
8
- "POT-Revision-Date: Fri Jan 08 2016 20:08:23 GMT+0100 (CET)\n"
9
- "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
- "Last-Translator: \n"
11
- "Language-Team: \n"
12
- "Language: \n"
13
- "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION\n"
14
- "MIME-Version: 1.0\n"
15
- "Content-Type: text/plain; charset=UTF-8\n"
16
- "Content-Transfer-Encoding: 8bit\n"
17
- "X-Poedit-SourceCharset: UTF-8\n"
18
- "X-Poedit-Basepath: .\n"
19
- "X-Poedit-SearchPath-0: ..\n"
20
- "X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
21
- "__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
22
- "_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
23
- "esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
24
- "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
- "X-Generator: Loco - https://localise.biz/"
26
-
27
- #. Name of the plugin
28
- msgid "Permalink Manager"
29
- msgstr ""
30
-
31
- #. URI of the plugin
32
- msgid "http://maciejbis.net"
33
- msgstr ""
34
-
35
- #. Description of the plugin
36
- msgid ""
37
- "A simple tool that allows to mass update of slugs that are used to build "
38
- "permalinks for Posts, Pages and Custom Post Types."
39
- msgstr ""
40
-
41
- #. Author of the plugin
42
- msgid "Maciej Bis"
43
- msgstr ""
44
-
45
- #: ../permalink-manager.php:89
46
- msgid "Find & Replace"
47
- msgstr ""
48
-
49
- #: ../permalink-manager.php:108
50
- msgid "Regenerate"
51
- msgstr ""
52
-
53
- #: ../permalink-manager.php:135
54
- msgid "Permalinks"
55
- msgstr ""
56
-
57
- #: ../permalink-manager.php:137
58
- msgid ""
59
- "You can disable/enable selected post types from the table below using "
60
- "<strong>\"Screen Options\"</strong> (click on the upper-right button to show "
61
- "it) section above."
62
- msgstr ""
63
-
64
- #: ../permalink-manager.php:140
65
- msgid "Find and replace"
66
- msgstr ""
67
-
68
- #: ../permalink-manager.php:142 ../permalink-manager.php:147
69
- msgid "<strong>You are doing it at your own risk!</strong>"
70
- msgstr ""
71
-
72
- #: ../permalink-manager.php:142
73
- msgid ""
74
- "A backup of MySQL database before using this tool is highly recommended. The "
75
- "search & replace operation might be not revertible!"
76
- msgstr ""
77
-
78
- #: ../permalink-manager.php:145
79
- msgid "Regenerate slugs"
80
- msgstr ""
81
-
82
- #: ../permalink-manager.php:147
83
- msgid ""
84
- "A backup of MySQL database before using this tool is highly recommended. The "
85
- "regenerate process of slugs might be not revertible!"
86
- msgstr ""
87
-
88
- #: ../permalink-manager.php:160
89
- msgid "by Maciej Bis"
90
- msgstr ""
91
-
92
- #: ../permalink-manager.php:210
93
- msgid "Go To Permalink Manager"
94
- msgstr ""
95
-
96
- #: ../permalink-manager.php:226
97
- msgid "Post Types"
98
- msgstr ""
99
-
100
- #: ../permalink-manager.php:228 ../permalink-manager.php:257 ../permalink-manager.
101
- #: php:273
102
- msgid "All Post Types"
103
- msgstr ""
104
-
105
- #: ../permalink-manager.php:232
106
- msgid "Post Statuses"
107
- msgstr ""
108
-
109
- #: ../permalink-manager.php:234 ../permalink-manager.php:263 ../permalink-manager.
110
- #: php:279
111
- msgid "All Post Statuses"
112
- msgstr ""
113
-
114
- #: ../permalink-manager.php:238
115
- msgid "Per page"
116
- msgstr ""
117
-
118
- #: ../permalink-manager.php:247
119
- msgid "Find ..."
120
- msgstr ""
121
-
122
- #: ../permalink-manager.php:251
123
- msgid "Replace with ..."
124
- msgstr ""
125
-
126
- #: ../permalink-manager.php:255 ../permalink-manager.php:271
127
- msgid "Post Types that should be affected"
128
- msgstr ""
129
-
130
- #: ../permalink-manager.php:261 ../permalink-manager.php:277
131
- msgid "Post Statuses that should be affected"
132
- msgstr ""
133
-
134
- #: ../permalink-manager.php:347
135
- #, php-format
136
- msgid "<strong>\"%1s\"</strong> field is empty!"
137
- msgstr ""
138
-
139
- #: ../permalink-manager.php:418
140
- #, php-format
141
- msgid "<strong>%d</strong> slug were updated!"
142
- msgid_plural "<strong>%d</strong> slugs were updated!"
143
- msgstr[0] ""
144
- msgstr[1] ""
145
-
146
- #: ../permalink-manager.php:419
147
- #, php-format
148
- msgid "<a href=\"%s\">Click here</a> to go to the list of updated slugs"
149
- msgstr ""
150
-
151
- #: ../permalink-manager.php:422
152
- msgid "<strong>No slugs</strong> were updated!"
153
- msgstr ""
154
-
155
- #: ../permalink-manager.php:435 ../permalink-manager.php:447 ../inc/permalink-
156
- #: manager-wp-table.php:30
157
- msgid "Title"
158
- msgstr ""
159
-
160
- #: ../permalink-manager.php:436 ../permalink-manager.php:448
161
- msgid "Old slug"
162
- msgstr ""
163
-
164
- #: ../permalink-manager.php:437 ../permalink-manager.php:449
165
- msgid "New slug"
166
- msgstr ""
167
-
168
- #: ../permalink-manager.php:447
169
- msgid "Show more details"
170
- msgstr ""
171
-
172
- #: ../permalink-manager.php:454
173
- msgid "List of updated posts"
174
- msgstr ""
175
-
176
- #: ../inc/permalink-manager-screen-options.php:21
177
- msgid "Apply"
178
- msgstr ""
179
-
180
- #: ../inc/permalink-manager-wp-table.php:31
181
- msgid "Slug"
182
- msgstr ""
183
-
184
- #: ../inc/permalink-manager-wp-table.php:32
185
- msgid "Date"
186
- msgstr ""
187
-
188
- #: ../inc/permalink-manager-wp-table.php:33
189
- msgid "Permalink"
190
- msgstr ""
191
-
192
- #: ../inc/permalink-manager-wp-table.php:34
193
- msgid "Post Status"
194
- msgstr ""
195
-
196
- #: ../inc/permalink-manager-wp-table.php:35
197
- msgid "Post Type"
198
- msgstr ""
199
-
200
- #: ../inc/permalink-manager-wp-table.php:81 ../inc/permalink-manager-wp-table.php:
201
- #: 81
202
- msgid "Edit"
203
- msgstr ""
204
-
205
- #: ../inc/permalink-manager-wp-table.php:82 ../inc/permalink-manager-wp-table.php:
206
- #: 82
207
- msgid "View"
208
- msgstr ""
209
-
210
- #: ../inc/permalink-manager-wp-table.php:124
211
- msgid "Update all slugs below"
212
- msgstr ""
213
-
214
- #: ../inc/permalink-manager-wp-table.php:125
215
- msgid "Update all slugs above"
216
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2017 Permalink Manager
2
+ # This file is distributed under the same license as the Permalink Manager package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Permalink Manager 0.5.1\n"
6
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/permalink-"
7
+ "manager\n"
8
+ "POT-Creation-Date: 2017-02-06 20:18:19+00:00\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
13
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
+ "Language-Team: LANGUAGE <LL@li.org>\n"
15
+
16
+ #: inc/permalink-manager-base-editor.php:27
17
+ #: inc/permalink-manager-editor.php:32
18
+ msgid "Post Type"
19
+ msgstr ""
20
+
21
+ #: inc/permalink-manager-base-editor.php:28
22
+ msgid "Custom Permalink Base/Permastruct"
23
+ msgstr ""
24
+
25
+ #: inc/permalink-manager-base-editor.php:87
26
+ #: includes/views/permalink-manager-settings.php:110
27
+ msgid "Save settings"
28
+ msgstr ""
29
+
30
+ #: inc/permalink-manager-editor.php:27
31
+ #: includes/core/permalink-manager-admin-functions.php:454
32
+ #: includes/core/permalink-manager-admin-functions.php:470
33
+ msgid "Title"
34
+ msgstr ""
35
+
36
+ #: inc/permalink-manager-editor.php:28
37
+ msgid "Post Name (Native Slug)"
38
+ msgstr ""
39
+
40
+ #: inc/permalink-manager-editor.php:30
41
+ msgid "Base & Slug (URI)"
42
+ msgstr ""
43
+
44
+ #: inc/permalink-manager-editor.php:31
45
+ msgid "Post Status"
46
+ msgstr ""
47
+
48
+ #: inc/permalink-manager-editor.php:84
49
+ #: includes/views/permalink-manager-uri-editor.php:130
50
+ msgid "Edit"
51
+ msgstr ""
52
+
53
+ #: inc/permalink-manager-editor.php:85
54
+ #: includes/views/permalink-manager-uri-editor.php:131
55
+ msgid "View"
56
+ msgstr ""
57
+
58
+ #: inc/permalink-manager-editor.php:111
59
+ msgid "Update all slugs below"
60
+ msgstr ""
61
+
62
+ #: inc/permalink-manager-editor.php:112
63
+ msgid "Update all slugs above"
64
+ msgstr ""
65
+
66
+ #: inc/permalink-manager-screen-options.php:22
67
+ msgid "Apply"
68
+ msgstr ""
69
+
70
+ #. #-#-#-#-# plugin.pot (Permalink Manager 0.5.1) #-#-#-#-#
71
+ #. Plugin Name of the plugin/theme
72
+ #: includes/core/permalink-manager-admin-functions.php:114
73
+ msgid "Permalink Manager"
74
+ msgstr ""
75
+
76
+ #: includes/core/permalink-manager-admin-functions.php:146
77
+ msgid "Go To Permalink Manager"
78
+ msgstr ""
79
+
80
+ #: includes/core/permalink-manager-admin-functions.php:199
81
+ msgid "Select all"
82
+ msgstr ""
83
+
84
+ #: includes/core/permalink-manager-admin-functions.php:200
85
+ msgid "Unselect all"
86
+ msgstr ""
87
+
88
+ #: includes/core/permalink-manager-admin-functions.php:379
89
+ msgid "by Maciej Bis"
90
+ msgstr ""
91
+
92
+ #: includes/core/permalink-manager-admin-functions.php:455
93
+ #: includes/core/permalink-manager-admin-functions.php:471
94
+ msgid "Old URI"
95
+ msgstr ""
96
+
97
+ #: includes/core/permalink-manager-admin-functions.php:456
98
+ #: includes/core/permalink-manager-admin-functions.php:472
99
+ msgid "New URI"
100
+ msgstr ""
101
+
102
+ #: includes/core/permalink-manager-admin-functions.php:457
103
+ #: includes/core/permalink-manager-admin-functions.php:473
104
+ msgid "Old Slug"
105
+ msgstr ""
106
+
107
+ #: includes/core/permalink-manager-admin-functions.php:458
108
+ #: includes/core/permalink-manager-admin-functions.php:474
109
+ msgid "New Slug"
110
+ msgstr ""
111
+
112
+ #: includes/core/permalink-manager-admin-functions.php:470
113
+ msgid "Show more details"
114
+ msgstr ""
115
+
116
+ #: includes/core/permalink-manager-admin-functions.php:479
117
+ msgid "List of updated items"
118
+ msgstr ""
119
+
120
+ #: includes/core/permalink-manager-uri-actions.php:46
121
+ msgid "<strong>%d</strong> slug was updated!"
122
+ msgid_plural "<strong>%d</strong> slugs were updated!"
123
+ msgstr[0] ""
124
+ msgstr[1] ""
125
+
126
+ #: includes/core/permalink-manager-uri-actions.php:47
127
+ msgid "<a href=\"%s\">Click here</a> to go to the list of updated slugs"
128
+ msgstr ""
129
+
130
+ #: includes/core/permalink-manager-uri-actions.php:52
131
+ msgid "<strong>No slugs</strong> were updated!"
132
+ msgstr ""
133
+
134
+ #: includes/views/permalink-manager-advanced.php:14
135
+ msgid "Advanced"
136
+ msgstr ""
137
+
138
+ #: includes/views/permalink-manager-advanced.php:31
139
+ msgid "Debug data"
140
+ msgstr ""
141
+
142
+ #: includes/views/permalink-manager-advanced.php:35
143
+ msgid "List of the URIs generated by this plugin."
144
+ msgstr ""
145
+
146
+ #: includes/views/permalink-manager-advanced.php:36
147
+ msgid "Array with URIs"
148
+ msgstr ""
149
+
150
+ #: includes/views/permalink-manager-advanced.php:42
151
+ msgid "List of the permastructures."
152
+ msgstr ""
153
+
154
+ #: includes/views/permalink-manager-advanced.php:43
155
+ msgid "Array with permastructures"
156
+ msgstr ""
157
+
158
+ #: includes/views/permalink-manager-advanced.php:49
159
+ msgid "Currently used plugin settings."
160
+ msgstr ""
161
+
162
+ #: includes/views/permalink-manager-advanced.php:50
163
+ msgid "Array with settings used in this plugin."
164
+ msgstr ""
165
+
166
+ #: includes/views/permalink-manager-advanced.php:56
167
+ msgid "Permalink hooks."
168
+ msgstr ""
169
+
170
+ #: includes/views/permalink-manager-advanced.php:57
171
+ msgid "Array with list of permalink hooks used on this website."
172
+ msgstr ""
173
+
174
+ #: includes/views/permalink-manager-permastructs.php:15
175
+ msgid "Permastructures"
176
+ msgstr ""
177
+
178
+ #: includes/views/permalink-manager-permastructs.php:48
179
+ msgid ""
180
+ "All available <a href=\"%s\" target=\"_blank\">structure tags</a> allowed "
181
+ "are listed below. Please note that some of them can be used only for "
182
+ "particular post types."
183
+ msgstr ""
184
+
185
+ #: includes/views/permalink-manager-permastructs.php:49
186
+ msgid "Each Custom Post Type should have unique permastructure."
187
+ msgstr ""
188
+
189
+ #: includes/views/permalink-manager-permastructs.php:50
190
+ msgid ""
191
+ "Please note that the following settings will be applied only to new posts."
192
+ "<br />If you would like to use the current permastructures settings, you "
193
+ "will need to regenerate the posts' URIs in <strong>\"Tools -> Regnerate/Reset"
194
+ "\"</strong> section."
195
+ msgstr ""
196
+
197
+ #: includes/views/permalink-manager-permastructs.php:51
198
+ msgid "To use the native permastruct please keep the field empty."
199
+ msgstr ""
200
+
201
+ #: includes/views/permalink-manager-permastructs.php:52
202
+ msgid "Usage Instructions"
203
+ msgstr ""
204
+
205
+ #: includes/views/permalink-manager-permastructs.php:55
206
+ msgid "Save permastructures"
207
+ msgstr ""
208
+
209
+ #: includes/views/permalink-manager-settings.php:15
210
+ msgid "Settings"
211
+ msgstr ""
212
+
213
+ #: includes/views/permalink-manager-settings.php:58
214
+ msgid "Display settings"
215
+ msgstr ""
216
+
217
+ #: includes/views/permalink-manager-settings.php:59
218
+ msgid "Adjust the data displayed in \"Permalink Editor\" section."
219
+ msgstr ""
220
+
221
+ #: includes/views/permalink-manager-settings.php:63
222
+ msgid "Per page"
223
+ msgstr ""
224
+
225
+ #: includes/views/permalink-manager-settings.php:68
226
+ msgid "Post statuses"
227
+ msgstr ""
228
+
229
+ #: includes/views/permalink-manager-settings.php:75
230
+ msgid "Post types"
231
+ msgstr ""
232
+
233
+ #: includes/views/permalink-manager-settings.php:83
234
+ msgid "Miscellaneous & SEO functions"
235
+ msgstr ""
236
+
237
+ #: includes/views/permalink-manager-settings.php:87
238
+ msgid "Primay term/category support"
239
+ msgstr ""
240
+
241
+ #: includes/views/permalink-manager-settings.php:89
242
+ #: includes/views/permalink-manager-settings.php:103
243
+ msgid "Enable"
244
+ msgstr ""
245
+
246
+ #: includes/views/permalink-manager-settings.php:89
247
+ #: includes/views/permalink-manager-settings.php:96
248
+ #: includes/views/permalink-manager-settings.php:103
249
+ msgid "Disable"
250
+ msgstr ""
251
+
252
+ #: includes/views/permalink-manager-settings.php:90
253
+ msgid ""
254
+ "Used to generate default permalinks in pages, posts & custom post types. "
255
+ "Works only when \"Yoast SEO\" plugin is enabled."
256
+ msgstr ""
257
+
258
+ #: includes/views/permalink-manager-settings.php:94
259
+ msgid "Redirect"
260
+ msgstr ""
261
+
262
+ #: includes/views/permalink-manager-settings.php:96
263
+ msgid "Enable \"301 redirect\""
264
+ msgstr ""
265
+
266
+ #: includes/views/permalink-manager-settings.php:96
267
+ msgid "Enable \"302 redirect\""
268
+ msgstr ""
269
+
270
+ #: includes/views/permalink-manager-settings.php:97
271
+ msgid ""
272
+ "If enabled - the visitors will be redirected from native permalinks to your "
273
+ "custom permalinks. Please note that the redirects will work correctly only "
274
+ "if native slug \"post name\" will not be changed."
275
+ msgstr ""
276
+
277
+ #: includes/views/permalink-manager-settings.php:101
278
+ msgid "Canonical redirect"
279
+ msgstr ""
280
+
281
+ #: includes/views/permalink-manager-settings.php:104
282
+ msgid ""
283
+ "This function allows Wordpress to correct the URLs used by the visitors."
284
+ msgstr ""
285
+
286
+ #: includes/views/permalink-manager-tools.php:15
287
+ msgid "Tools"
288
+ msgstr ""
289
+
290
+ #: includes/views/permalink-manager-tools.php:18
291
+ #: includes/views/permalink-manager-tools.php:83
292
+ msgid "Find and replace"
293
+ msgstr ""
294
+
295
+ #: includes/views/permalink-manager-tools.php:22
296
+ msgid "Regenerate/Reset"
297
+ msgstr ""
298
+
299
+ #: includes/views/permalink-manager-tools.php:32
300
+ msgid ""
301
+ "<h4>A MySQL backup is highly recommended before using \"<em>Custom & native "
302
+ "slugs (post names)</em>\" mode!</h4>With this mode selected, "
303
+ "<strong>post_name</strong> field (native slug) will be changed directly in "
304
+ "<a href=\"%s\"><strong>\"posts\"</strong></a> database table."
305
+ msgstr ""
306
+
307
+ #: includes/views/permalink-manager-tools.php:44
308
+ msgid "Find ..."
309
+ msgstr ""
310
+
311
+ #: includes/views/permalink-manager-tools.php:50
312
+ msgid "Replace with ..."
313
+ msgstr ""
314
+
315
+ #: includes/views/permalink-manager-tools.php:57
316
+ #: includes/views/permalink-manager-tools.php:95
317
+ msgid "Select mode"
318
+ msgstr ""
319
+
320
+ #: includes/views/permalink-manager-tools.php:59
321
+ #: includes/views/permalink-manager-tools.php:97
322
+ msgid "Full URIs"
323
+ msgstr ""
324
+
325
+ #: includes/views/permalink-manager-tools.php:59
326
+ #: includes/views/permalink-manager-tools.php:97
327
+ msgid "Only custom slugs"
328
+ msgstr ""
329
+
330
+ #: includes/views/permalink-manager-tools.php:59
331
+ #: includes/views/permalink-manager-tools.php:97
332
+ msgid "Custom & native slugs (post names)"
333
+ msgstr ""
334
+
335
+ #: includes/views/permalink-manager-tools.php:63
336
+ #: includes/views/permalink-manager-tools.php:100
337
+ msgid "Filter by post types"
338
+ msgstr ""
339
+
340
+ #: includes/views/permalink-manager-tools.php:71
341
+ #: includes/views/permalink-manager-tools.php:108
342
+ msgid "Filter by post statuses"
343
+ msgstr ""
344
+
345
+ #: includes/views/permalink-manager-tools.php:80
346
+ #: includes/views/permalink-manager-tools.php:117
347
+ msgid "Important notes"
348
+ msgstr ""
349
+
350
+ #: includes/views/permalink-manager-tools.php:119
351
+ msgid "Regenerate"
352
+ msgstr ""
353
+
354
+ #: includes/views/permalink-manager-uri-editor.php:19
355
+ msgid "Permalink editor"
356
+ msgstr ""
357
+
358
+ #: includes/views/permalink-manager-uri-editor.php:76
359
+ msgid "Post title"
360
+ msgstr ""
361
+
362
+ #: includes/views/permalink-manager-uri-editor.php:77
363
+ msgid "Post name (native slug)"
364
+ msgstr ""
365
+
366
+ #: includes/views/permalink-manager-uri-editor.php:79
367
+ msgid "Full URI & Permalink"
368
+ msgstr ""
369
+
370
+ #: includes/views/permalink-manager-uri-editor.php:80
371
+ msgid "Post status"
372
+ msgstr ""
373
+
374
+ #: includes/views/permalink-manager-uri-editor.php:157
375
+ msgid "Update all the URIs below"
376
+ msgstr ""
377
+
378
+ #: includes/views/permalink-manager-uri-editor.php:158
379
+ msgid "Update all the URIs above"
380
+ msgstr ""
381
+
382
+ #. #-#-#-#-# plugin.pot (Permalink Manager 0.5.1) #-#-#-#-#
383
+ #. Plugin URI of the plugin/theme
384
+ #. #-#-#-#-# plugin.pot (Permalink Manager 0.5.1) #-#-#-#-#
385
+ #. Author URI of the plugin/theme
386
+ msgid "http://maciejbis.net/"
387
+ msgstr ""
388
+
389
+ #. Description of the plugin/theme
390
+ msgid ""
391
+ "A simple tool that allows to mass update of slugs that are used to build "
392
+ "permalinks for Posts, Pages and Custom Post Types."
393
+ msgstr ""
394
+
395
+ #. Author of the plugin/theme
396
+ msgid "Maciej Bis"
397
+ msgstr ""
out/permalink-manager-admin.css ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Permalink Manager CSS
3
+ */
4
+ #permalink-manager #plugin-name-heading a{color:#959595;font-size:60%;text-decoration:none}
5
+ #permalink-manager #permalink-manager-tab-nav > a:first-child{margin-left:0}
6
+ #permalink-manager h4{font-size:18px;margin-bottom:10px}
7
+ #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
8
+ #permalink-manager .settings-select{min-width:200px}
9
+ #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
10
+ #permalink-manager .margin-top{margin-top:15px}
11
+
12
+ #permalink-manager .subsubsub{display:block;width:100%;overflow:hidden;margin-bottom:8px}
13
+ #permalink-manager .subsubsub li:before{content:" | "}
14
+ #permalink-manager .subsubsub li:first-child:before{content:"";color:#aaa}
15
+ #permalink-manager .tablenav{margin:15px 0;height:auto}
16
+ #permalink-manager .tablenav.top{margin-top:0}
17
+ #permalink-manager .tablenav .actions{padding:0;overflow:visible}
18
+ #permalink-manager .column-post_type,#permalink-manager .column-post_status{width:13%}
19
+ #permalink-manager .post_name input{max-width:100%}
20
+ #permalink-manager .post_permalink a,#permalink-manager .post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
21
+ #permalink-manager .post_permalink{margin-top:5px;display:block}
22
+
23
+ #permalink-manager .alert{line-height:19px;padding:11px 15px;margin:15px 0}
24
+ #permalink-manager .alert p{margin-top:0;line-height:200%}
25
+ #permalink-manager .alert ul,#permalink-manager .alert ol{margin-top:0;margin-bottom:0}
26
+ #permalink-manager .alert p:last-of-type,#permalink-manager .alert li:last-of-type{margin-bottom:0}
27
+ #permalink-manager .warning{background:#dc3232}
28
+ #permalink-manager .warning,#permalink-manager .warning a{color:#fff}
29
+ #permalink-manager .info{background:#f9f9f9}
30
+ #permalink-manager .section-notes,#permalink-manager .short-pre,#permalink-manager .short-textarea{padding:15px;font-size:13px;margin-top:15px;line-height:20px;background:#e5e5e5;border:1px solid #ccc;color:#555}
31
+ #permalink-manager .section-notes a,#permalink-manager .section-notes h3{color:#111}
32
+ #permalink-manager .section-notes h3,#permalink-manager .section-notes h4{margin-top:0}
33
+ #permalink-manager .section-notes h4{font-size:14px}
34
+ #permalink-manager .section-notes code{font-size:11px;background:#444;color:#fff}
35
+ #permalink-manager .section-notes ol{margin-top:0;margin-bottom:0}
36
+ #permalink-manager .section-notes ol li:last-of-type{margin-bottom:0}
37
+ #permalink-manager .short-pre,#permalink-manager .short-textarea{height:150px;overflow:auto;max-width:100%;display:block}
38
+
39
+ #permalink-manager .checkbox_actions{padding-top:10px;border-top:1px solid #ddd}
40
+ #permalink-manager .extra-links{margin-top:5px;font-size:12px}
41
+ #permalink-manager .extra-links a{background:#e5e5e5;border:1px solid #ccc;padding:3px 5px;color:#555;display:inline-block;text-decoration:none}
42
+ #permalink-manager .checkboxes{margin-left:-15px;margin-right:15px;overflow:hidden;display:block}
43
+ #permalink-manager .checkboxes > label{display:inline-block;width:33%;float:left;padding:0 15px;box-sizing:border-box;padding-bottom:5px}
44
+ #permalink-manager .field-description{font-size:12px}
45
+ #permalink-manager .appended-row td{padding-left:0;padding-right:0}
46
+
47
+ /**
48
+ * Columns
49
+ */
50
+ #permalink-manager .columns-container{overflow:hidden;margin-left:-15px;margin-right:-15px;clear:both}
51
+ #permalink-manager .columns-container .column{float:left;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-box-sizing:border-box;overflow:hidden}
52
+ #permalink-manager .columns-container .column-1_2{width:50%}
53
+ #permalink-manager .columns-container .column-1_3{width:33.33%}
54
+ #permalink-manager .columns-container .column-2_3{width:66.67%}
55
+
56
+ /**
57
+ * Breakpoints
58
+ */
59
+ @media only screen and (max-width : 782px) {
60
+ #permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-1_3,#permalink-manager .columns-container .column-2_3{width:100%}
61
+ }
out/permalink-manager-admin.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function() {
2
+
3
+ /*
4
+ * "(Un)select all" checkboxes
5
+ */
6
+ var checkbox_actions = ['select_all', 'unselect_all'];
7
+ checkbox_actions.forEach(function(element) {
8
+ jQuery('.' + element).on('click', function() {
9
+ jQuery(this).parents('td').find('.checkboxes input[type="checkbox"]').each(function() {
10
+ var action = (element == 'select_all') ? true : false;
11
+ jQuery(this).prop('checked', action);
12
+ });
13
+
14
+ return false;
15
+ });
16
+ });
17
+
18
+ jQuery('.checkboxes label').not('input').on('click', function(ev) {
19
+ var input = jQuery(this).find("input");
20
+ if(!jQuery(ev.target).is("input")) {
21
+ input.prop('checked', !(input.prop("checked")));
22
+ }
23
+ });
24
+
25
+ });
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.4.9
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
@@ -12,494 +12,121 @@
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);
@@ -508,7 +135,6 @@ class Permalink_Manager_Class {
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]))) {
@@ -523,16 +149,31 @@ class Permalink_Manager_Class {
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);
@@ -570,12 +211,14 @@ class Permalink_Manager_Class {
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
@@ -594,194 +237,40 @@ class Permalink_Manager_Class {
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();
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.5.4
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
12
  * Text Domain: permalink-manager
13
  * Domain Path: /languages
14
  */
 
15
  // If this file is called directly, abort.
16
  if ( ! defined( 'WPINC' ) ) {
17
  die;
18
  }
19
 
20
  // Define the directories used to load plugin files.
21
+ define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
22
+ define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
23
+ define( 'PERMALINK_MANAGER_VERSION', '0.5.4' );
24
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
25
+ define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
26
  define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
27
  define( 'PERMALINK_MANAGER_WEBSITE', 'http://maciejbis.net' );
 
 
28
 
29
  class Permalink_Manager_Class {
30
 
31
+ public $permalink_manager, $permalink_manager_options_page, $permalink_manager_options;
32
+ public $sections, $functions, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  /**
35
+ * Get options from DB, load subclasses & hooks
36
  */
37
+ public function __construct() {
38
+ $this->include_subclassess();
39
+ $this->run_subclasses();
40
+ $this->register_init_hooks();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
  /**
44
+ * Include back-end classess and set their instances
45
  */
46
+ function include_subclassess() {
47
+ // Load back-end functions
48
+ foreach(array('helper-functions', 'post-uri-functions', 'admin-functions', 'uri-actions') as $class) {
49
+ require_once PERMALINK_MANAGER_DIR . "/includes/core/permalink-manager-{$class}.php";
 
 
 
 
 
 
50
  }
51
 
52
+ // WP_List_Table needed for post types & taxnomies editors
53
+ if( ! class_exists( 'WP_List_Table' ) ) {
54
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
55
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ // Load section classes
58
+ foreach(array('uri-editor', 'tools', 'permastructs', 'settings', 'advanced') as $class) {
59
+ require_once PERMALINK_MANAGER_DIR . "/includes/views/permalink-manager-{$class}.php";
60
+ }
 
61
  }
62
 
63
  /**
64
+ * Load front-end classes and set their instances.
65
  */
66
+ function run_subclasses() {
67
+ $this->functions['helper_functions'] = new Permalink_Manager_Helper_Functions();
68
+ $this->functions['admin_functions'] = new Permalink_Manager_Admin_Functions();
69
+ $this->functions['post_uri_functions'] = new Permalink_Manager_Post_URI_Functions();
70
+ $this->functions['uri_actions'] = new Permalink_Manager_Uri_Actions();
71
+ $this->sections['uri_editor'] = new Permalink_Manager_Uri_Editor();
72
+ $this->sections['tools'] = new Permalink_Manager_Tools();
73
+ $this->sections['permastructs'] = new Permalink_Manager_Permastructs();
74
+ $this->sections['settings'] = new Permalink_Manager_Settings();
75
+ $this->sections['advanced'] = new Permalink_Manager_Advanced();
76
  }
77
 
78
  /**
79
+ * Register general hooks
80
  */
81
+ public function register_init_hooks() {
82
+ // Localize plugin
83
+ add_action( 'plugins_loaded', array($this, 'localize_me'), 1 );
 
84
 
85
+ // Load options
86
+ add_action( 'init', array($this, 'get_options_and_globals'), 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ // Use the URIs set in this plugin + redirect from old URIs to new URIs + adjust canonical redirect settings
89
+ add_action( 'wp', array($this, 'disable_canonical_redirect'), 0, 1 );
90
+ add_action( 'template_redirect', array($this, 'redirect_to_new_uri'), 999);
91
+ add_filter( 'request', array($this, 'detect_post'), 0, 1 );
92
  }
93
 
94
  /**
95
+ * Localize this plugin
96
  */
97
+ function localize_me() {
98
+ load_plugin_textdomain( 'permalink-manager', false, PERMALINK_MANAGER_DIR );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
 
101
  /**
102
+ * Get options values & set global
103
  */
104
+ public function get_options_and_globals() {
105
+ // 1. Globals with data stored in DB
106
+ global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs;
 
 
107
 
108
+ $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager'));
109
+ $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris'));
110
+ $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs'));
111
 
112
+ // 2. Globals used to display additional content (eg. alerts)
113
+ global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
114
 
115
+ $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', '');
116
+ $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', '');
117
  }
118
 
119
  /**
120
+ * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin
121
  */
122
  function detect_post($query) {
123
+ global $wpdb, $permalink_manager_uris;
 
124
 
125
  // Used in debug mode
126
  $old_query = $query;
127
 
 
128
  $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
129
+ $url = str_replace(home_url(), "{$protocol}{$_SERVER['HTTP_HOST']}", "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); // Fix for Wordpress installed in subdirectories
 
130
 
131
  // Remove .html suffix from URL and query (URLs ended with .html work as aliases)
132
  $url = str_replace(".html", "", $url);
135
 
136
  // Check if it is correct URL
137
  if (filter_var($url, FILTER_VALIDATE_URL)) {
 
138
  // Separate endpoints (if set) - support for comment pages will be added later
139
  preg_match("/(.*)\/(page|feed|embed|attachment|track)\/(.*)/", $url, $url_with_endpoints);
140
  if(isset($url_with_endpoints[3]) && !(empty($url_with_endpoints[3]))) {
149
  if(empty($uri)) return $query;
150
 
151
  // Check if current URL is assigned to any post
152
+ if(!(is_array($permalink_manager_uris))) return $query;
153
+ $post_id = array_search($uri, $permalink_manager_uris);
 
154
 
155
  // Check again in case someone added .html suffix to particular post (with .html suffix)
156
+ $post_id = (empty($post_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $post_id;
157
 
158
  if(isset($post_id) && is_numeric($post_id)) {
159
  // Check if it is revision (hotfix) and use original post ID instead of revision ID
160
  $is_revision = wp_is_post_revision($post_id);
161
+
162
+ // Debug for @andresgl
163
+ if(isset($_REQUEST['debug_detect_post'])) {
164
+ $post_to_load = (is_object(get_post($post_id))) ? get_post($post_id) : 'no object!';
165
+ $revision_post_to_load = (is_object(get_post($is_revision))) ? get_post($is_revision) : 'no object!';
166
+
167
+ $debug_array = array(
168
+ 'original_post_id' => $post_id,
169
+ 'original_post' => $post_to_load,
170
+ 'revision_post_id' => $is_revision,
171
+ 'revision_post' => $revision_post_to_load,
172
+ );
173
+
174
+ wp_die("<pre>" . print_r($debug_array, true) . "</pre>");
175
+ }
176
+
177
  $post_id = ($is_revision) ? $is_revision : $post_id;
178
 
179
  $post_to_load = get_post($post_id);
211
  $query[$post_type] = $original_page_uri;
212
  }
213
 
214
+ // Make the redirects more clever - see redirect_to_new_uri() method
215
+ $query['do_not_redirect'] = 1;
216
+
217
  // Add endpoint
218
  if(isset($endpoint_value) && !(empty($endpoint_value))) {
219
  $query[$endpoint] = $endpoint_value;
220
  }
221
  }
 
222
  }
223
 
224
  // Debug mode
237
  }
238
 
239
  function redirect_to_new_uri() {
240
+ global $wp, $wp_query, $permalink_manager_uris, $permalink_manager_options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
+ // Affect only posts with custom URI and old URIs
243
+ if(is_singular() && isset($permalink_manager_uris[$wp_query->queried_object_id]) && empty($wp_query->query['do_not_redirect'])) {
244
+ $current_url = home_url(add_query_arg(array(),$wp->request));
245
+ $native_uri = Permalink_Manager_Post_URI_Functions::get_default_post_uri($wp_query->queried_object_id, true);
 
 
246
 
247
+ $active_permalink = str_replace($native_uri, $permalink_manager_uris[$wp_query->queried_object_id], $current_url);
 
 
 
 
 
248
  }
249
 
250
+ // Get the redirection mode
251
+ $redirect_mode = $permalink_manager_options['miscellaneous']['redirect'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ // Ignore default URIs (or do nothing if redirects are disabled)
254
+ if(!empty($active_permalink) && !empty($redirect_mode)) {
255
+ wp_redirect($active_permalink, $redirect_mode);
256
+ exit();
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
 
 
 
258
  }
259
 
260
+ function disable_canonical_redirect() {
261
+ global $permalink_manager_options;
262
+ if(!($permalink_manager_options['miscellaneous']['canonical_redirect'])) {
263
+ remove_action('template_redirect', 'redirect_canonical');
 
 
 
 
 
264
  }
 
 
265
  }
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  }
268
 
269
  /**
270
  * Begins execution of the plugin.
271
  */
272
  function run_permalink_manager() {
 
 
 
 
 
 
 
 
273
  $Permalink_Manager_Class = new Permalink_Manager_Class();
 
 
274
  }
275
 
276
  run_permalink_manager();