Permalink Manager Lite - Version 2.1.1

Version Description

  • Support for draft custom permalinks
  • Support for WP All Import plugin, now the custom permalinks can be defined directly in XML, CSV, ZIP, GZIP, GZ, JSON, SQL, TXT, DAT or PSV import files.
  • Hotfix for Permalink_Manager_Pro_Functions::save_redirects() method - now the custom redirects are correctly saved when a custom permalink is updated.
  • Hotfix for "Language name added as a parameter" mode in "WPML Language URL format" settings.
  • Hotfix for canonical redirect triggered by WPML.
  • Better support for non-latin letters in custom URIs & redirects
  • Better support for endpoints
  • Searchbox in URI Editors
Download this release

Release Info

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

Code changes from version 2.0.6.3 to 2.1.1

README.txt CHANGED
@@ -7,7 +7,7 @@ Tags: urls, permalinks, custom permalinks, url, permalink, woocommerce permalink
7
  Requires at least: 4.4.0
8
  Requires PHP: 5.4
9
  Tested up to: 4.9
10
- Stable tag: 2.0.6.3
11
 
12
  Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
13
 
@@ -85,6 +85,35 @@ A. Currently there is no 100% guarantee that Permalink Manager will work correct
85
 
86
  == Changelog ==
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  = 2.0.6.2/2.0.6.3 =
89
  * Japaneese translation added
90
  * Some minor improvements
7
  Requires at least: 4.4.0
8
  Requires PHP: 5.4
9
  Tested up to: 4.9
10
+ Stable tag: 2.1.1
11
 
12
  Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
13
 
85
 
86
  == Changelog ==
87
 
88
+ = 2.1.1 =
89
+ * Support for draft custom permalinks
90
+ * Support for WP All Import plugin, now the custom permalinks can be defined directly in XML, CSV, ZIP, GZIP, GZ, JSON, SQL, TXT, DAT or PSV import files.
91
+ * Hotfix for Permalink_Manager_Pro_Functions::save_redirects() method - now the custom redirects are correctly saved when a custom permalink is updated.
92
+ * Hotfix for "Language name added as a parameter" mode in "WPML Language URL format" settings.
93
+ * Hotfix for canonical redirect triggered by WPML.
94
+ * Better support for non-latin letters in custom URIs & redirects
95
+ * Better support for endpoints
96
+ * Searchbox in URI Editors
97
+
98
+ = 2.1.0 =
99
+ * Support for "url_to_postid" function
100
+ * Bulk tools use now AJAX & transients to prevent timeout when large number of posts/terms is processed
101
+ * Fix for multi-domain language setup in WPML
102
+
103
+ = 2.0.6.5 =
104
+ * Support for %__sku% permastructure tag (WooCommerce) added - now SKU number can be added to the custom permalinks (Permalink Manager Pro)
105
+ * Hotfix for license validation system
106
+
107
+ = 2.0.6.4 =
108
+ * Code optimization
109
+ * New filter: permalink_manager_fix_uri_duplicates
110
+ * Possibility to display the native slug field
111
+ * Hotfix for license validation functions
112
+
113
+ = 2.0.6.3.2 =
114
+ * Support added for Revisionize plugin
115
+ * Minor tweaks
116
+
117
  = 2.0.6.2/2.0.6.3 =
118
  * Japaneese translation added
119
  * Some minor improvements
includes/core/permalink-manager-actions.php CHANGED
@@ -5,9 +5,12 @@
5
  class Permalink_Manager_Actions extends Permalink_Manager_Class {
6
 
7
  public function __construct() {
8
- add_action('admin_init', array($this, 'trigger_action'), 999);
9
  add_action('admin_init', array($this, 'extra_actions'));
10
 
 
 
 
11
  add_action('clean_permalinks_event', array($this, 'clean_permalinks_hook'));
12
  add_action('init', array($this, 'clean_permalinks_cronjob'));
13
  }
@@ -16,24 +19,25 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
16
  * Actions
17
  */
18
  public function trigger_action() {
19
- global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
20
 
21
  // 1. Check if the form was submitted
22
  if(empty($_POST)) { return; }
23
 
24
  $actions_map = array(
25
  'uri_editor' => array('function' => 'update_all_permalinks', 'display_uri_table' => true),
26
- 'regenerate' => array('function' => 'regenerate_all_permalinks', 'display_uri_table' => true),
27
- 'find_and_replace' => array('function' => 'find_and_replace', 'display_uri_table' => true),
28
  'permalink_manager_options' => array('function' => 'save_settings'),
29
  'permalink_manager_permastructs' => array('function' => 'save_permastructures'),
30
- 'flush_sitemaps' => array('function' => 'save_permastructures'),
31
  'import' => array('function' => 'import_custom_permalinks_uris'),
32
  );
33
 
34
  // 2. Find the action
35
  foreach($actions_map as $action => $map) {
36
  if(isset($_POST[$action]) && wp_verify_nonce($_POST[$action], 'permalink-manager')) {
 
37
  $output = call_user_func(array($this, $map['function']));
38
 
39
  // Get list of updated URIs
@@ -49,23 +53,14 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
49
 
50
  // 3. Display the slugs table (and append the globals)
51
  if(isset($updated_slugs_count)) {
52
- if($updated_slugs_count > 0) {
53
- $updated_title = __('List of updated items', 'bis');
54
- $alert_content = sprintf( _n( '<strong>%d</strong> slug was updated!', '<strong>%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
55
- $alert_content .= sprintf( __( '<a %s>Click here</a> to go to the list of updated slugs', 'permalink-manager' ), "href=\"#updated-list\" title=\"{$updated_title}\"");
56
-
57
- $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message($alert_content, 'updated');
58
- $permalink_manager_after_sections_html .= Permalink_Manager_Admin_Functions::display_updated_slugs($updated_slugs_array);
59
- } else {
60
- $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(__( '<strong>No slugs</strong> were updated!', 'permalink-manager' ), 'error');
61
- }
62
  }
63
  }
64
 
65
  /**
66
  * Save settings
67
  */
68
- public static function save_settings($field = false, $value = false) {
69
  global $permalink_manager_options, $permalink_manager_before_sections_html;
70
 
71
  // Info: The settings array is used also by "Screen Options"
@@ -91,7 +86,123 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
91
  update_option('permalink-manager', $new_options);
92
 
93
  // Display the message
94
- $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(__( 'The settings are saved!', 'permalink-manager' ), 'updated');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
 
97
  /**
@@ -143,20 +254,13 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
143
  foreach($group as $element => $permastruct) {
144
  // Trim slashes
145
  $permastruct = trim($permastruct, "/");
146
-
147
- // Do not store default permastructures
148
- // $default_permastruct = ($group_name == 'post_types') ? Permalink_Manager_Helper_Functions::get_default_permastruct($element, true) : "";
149
- // if($permastruct == $default_permastruct) { unset($group[$element]); }
150
  }
151
- // Do not store empty permastructures
152
- // $new_options[$group_name] = array_filter($group);
153
  } else {
154
  unset($new_options[$group_name]);
155
  }
156
  }
157
 
158
  // Override the global with settings
159
- // $permalink_manager_permastructs = $new_options = $new_options;
160
  $permalink_manager_permastructs = $new_options;
161
 
162
  // Save the settings in database
@@ -176,21 +280,33 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
176
  $removed_uris = 0;
177
  $removed_redirects = 0;
178
 
179
- foreach($permalink_manager_uris as $element_id => $uri) {
 
 
 
 
180
  $count = self::clear_single_element_uris_and_redirects($element_id, true);
181
 
182
  $removed_uris = (!empty($count[0])) ? $count[0] + $removed_uris : $removed_uris;
183
  $removed_redirects = (!empty($count[1])) ? $count[1] + $removed_redirects : $removed_redirects;
184
  }
185
 
 
 
 
 
 
 
 
 
186
  // Save cleared URIs & Redirects
187
  if($removed_uris > 0 || $removed_redirects > 0) {
188
  update_option('permalink-manager-uris', array_filter($permalink_manager_uris));
189
  update_option('permalink-manager-redirects', array_filter($permalink_manager_redirects));
190
 
191
- $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(sprintf(__( '%d Custom URIs and %d Custom Redirects were removed!', 'permalink-manager' ), $removed_uris, $removed_redirects), 'updated');
192
  } else {
193
- $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(__( 'No Custom URIs or Custom Redirects were removed!', 'permalink-manager' ), 'error');
194
  }
195
  }
196
 
@@ -283,6 +399,40 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
283
  }
284
  }
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  /**
287
  * Remove custom URI & redirects for any requested post or term
288
  */
@@ -329,39 +479,23 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
329
  }
330
 
331
  /**
332
- * "Find and replace" in "Tools"
333
- */
334
- function find_and_replace() {
335
- // Check if posts or terms should be updated
336
- if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
337
- return Permalink_Manager_URI_Functions_Tax::find_and_replace();
338
- } else {
339
- return Permalink_Manager_URI_Functions_Post::find_and_replace();
340
- }
341
- }
342
 
343
- /**
344
- * Regenerate all permalinks in "Tools"
345
- */
346
- function regenerate_all_permalinks() {
347
- // Check if posts or terms should be updated
348
- if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
349
- return Permalink_Manager_URI_Functions_Tax::regenerate_all_permalinks();
350
- } else {
351
- return Permalink_Manager_URI_Functions_Post::regenerate_all_permalinks();
352
- }
353
- }
354
 
355
- /**
356
- * Update all permalinks in "Permalink Editor"
357
- */
358
- function update_all_permalinks() {
359
- // Check if posts or terms should be updated
360
- if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
361
- return Permalink_Manager_URI_Functions_Tax::update_all_permalinks();
362
- } else {
363
- return Permalink_Manager_URI_Functions_Post::update_all_permalinks();
364
  }
 
 
365
  }
366
 
367
  /**
5
  class Permalink_Manager_Actions extends Permalink_Manager_Class {
6
 
7
  public function __construct() {
8
+ add_action('admin_init', array($this, 'trigger_action'), 9);
9
  add_action('admin_init', array($this, 'extra_actions'));
10
 
11
+ // Ajax-based bulk tools
12
+ add_action('wp_ajax_pm_bulk_tools', array($this, 'pm_bulk_tools'));
13
+
14
  add_action('clean_permalinks_event', array($this, 'clean_permalinks_hook'));
15
  add_action('init', array($this, 'clean_permalinks_cronjob'));
16
  }
19
  * Actions
20
  */
21
  public function trigger_action() {
22
+ global $permalink_manager_after_sections_html;
23
 
24
  // 1. Check if the form was submitted
25
  if(empty($_POST)) { return; }
26
 
27
  $actions_map = array(
28
  'uri_editor' => array('function' => 'update_all_permalinks', 'display_uri_table' => true),
29
+ //'regenerate' => array('function' => 'regenerate_all_permalinks', 'display_uri_table' => true),
30
+ //'find_and_replace' => array('function' => 'find_and_replace', 'display_uri_table' => true),
31
  'permalink_manager_options' => array('function' => 'save_settings'),
32
  'permalink_manager_permastructs' => array('function' => 'save_permastructures'),
33
+ 'flush_sitemaps' => array('function' => 'flush_sitemaps'),
34
  'import' => array('function' => 'import_custom_permalinks_uris'),
35
  );
36
 
37
  // 2. Find the action
38
  foreach($actions_map as $action => $map) {
39
  if(isset($_POST[$action]) && wp_verify_nonce($_POST[$action], 'permalink-manager')) {
40
+ // Execute the function
41
  $output = call_user_func(array($this, $map['function']));
42
 
43
  // Get list of updated URIs
53
 
54
  // 3. Display the slugs table (and append the globals)
55
  if(isset($updated_slugs_count)) {
56
+ $permalink_manager_after_sections_html .= Permalink_Manager_Admin_Functions::display_updated_slugs($updated_slugs_array);
 
 
 
 
 
 
 
 
 
57
  }
58
  }
59
 
60
  /**
61
  * Save settings
62
  */
63
+ public static function save_settings($field = false, $value = false, $display_alert = true) {
64
  global $permalink_manager_options, $permalink_manager_before_sections_html;
65
 
66
  // Info: The settings array is used also by "Screen Options"
86
  update_option('permalink-manager', $new_options);
87
 
88
  // Display the message
89
+ $permalink_manager_before_sections_html .= ($display_alert) ? Permalink_Manager_Admin_Functions::get_alert_message(__( 'The settings are saved!', 'permalink-manager' ), 'updated') : "";
90
+ }
91
+
92
+ /**
93
+ * Trigger bulk tools via AJAX
94
+ */
95
+ function pm_bulk_tools() {
96
+ // Define variables
97
+ $return = array('alert' => Permalink_Manager_Admin_Functions::get_alert_message(__( '<strong>No slugs</strong> were updated!', 'permalink-manager' ), 'error updated_slugs'));
98
+
99
+ // Get the name of the function
100
+ if(isset($_POST['regenerate']) && wp_verify_nonce($_POST['regenerate'], 'permalink-manager')) {
101
+ $function_name = 'regenerate_all_permalinks';
102
+ $uniq_id = $_POST['pm_session_id'];
103
+ } else if(isset($_POST['find_and_replace']) && wp_verify_nonce($_POST['find_and_replace'], 'permalink-manager') && !empty($_POST['old_string']) && !empty($_POST['new_string'])) {
104
+ $function_name = 'find_and_replace';
105
+ $uniq_id = $_POST['pm_session_id'];
106
+ }
107
+
108
+ // Check if both strings are set for "Find and replace" tool
109
+ if(!empty($function_name)) {
110
+ // Get the mode
111
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : 'custom_uris';
112
+
113
+ // Get the content type
114
+ if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
115
+ $class_name = 'Permalink_Manager_URI_Functions_Tax';
116
+ } else {
117
+ $class_name = 'Permalink_Manager_URI_Functions_Post';
118
+ }
119
+
120
+ // Get items (try to get them from transient)
121
+ $items = get_transient("pm_{$uniq_id}");
122
+ $progress = get_transient("pm_{$uniq_id}_progress");
123
+
124
+ $first_chunk = true;
125
+ $chunk_size = 50;
126
+
127
+ if(empty($items)) {
128
+ $items = $class_name::get_items();
129
+
130
+ // Set stats (to display the progress)
131
+ $total = count($items);
132
+
133
+ // Split items array into chunks and save them to transient
134
+ $items = array_chunk($items, $chunk_size);
135
+
136
+ set_transient("pm_{$uniq_id}", $items, 300);
137
+ set_transient("pm_{$uniq_id}_progress", 0, 300);
138
+ }
139
+
140
+ // Get homepage URL and ensure that it ends with slash
141
+ $home_url = Permalink_Manager_Helper_Functions::get_permalink_base() . "/";
142
+
143
+ // Process the variables from $_POST object
144
+ $old_string = (!empty($_POST['old_string'])) ? str_replace($home_url, '', esc_sql($_POST['old_string'])) : '';
145
+ $new_string = (!empty($_POST['old_string'])) ? str_replace($home_url, '', esc_sql($_POST['new_string'])) : '';
146
+
147
+ // Process only one subarray
148
+ if(!empty($items[0])) {
149
+ $chunk = $items[0];
150
+
151
+ // Remove from array & update the transient
152
+ unset($items[0]);
153
+ $items = array_values($items);
154
+ set_transient("pm_{$uniq_id}", $items, 300);
155
+
156
+ // Check if posts or terms should be updated
157
+ if($function_name == 'find_and_replace') {
158
+ $output = $class_name::find_and_replace($chunk, $mode, $old_string, $new_string);
159
+ } else {
160
+ $output = $class_name::regenerate_all_permalinks($chunk, $mode);
161
+ }
162
+
163
+ if(!empty($output['updated_count'])) {
164
+ $return = array_merge($return, (array) Permalink_Manager_Admin_Functions::display_updated_slugs($output['updated'], true, $first_chunk));
165
+ $return['updated_count'] = $output['updated_count'];
166
+ }
167
+
168
+ // Send total number of processed items with a first chunk
169
+ if(!empty($total)) {
170
+ $return['total'] = $total;
171
+ }
172
+
173
+ // Check if there are any chunks left
174
+ if(count($items) > 0) {
175
+ // Update progress
176
+ $progress += $chunk_size;
177
+ set_transient("pm_{$uniq_id}_progress", $progress, 300);
178
+
179
+ $return['left_chunks'] = true;
180
+ $return['progress'] = $progress;
181
+ } else {
182
+ delete_transient("pm_{$uniq_id}");
183
+ delete_transient("pm_{$uniq_id}_progress");
184
+ }
185
+ }
186
+ }
187
+
188
+ wp_send_json($return);
189
+ die();
190
+ }
191
+
192
+ /**
193
+ * Update all permalinks in "Permalink Editor"
194
+ */
195
+ function update_all_permalinks() {
196
+ // Do nothing if search query is not empty
197
+ if(!empty($_REQUEST['search-submit'])) {
198
+ return;
199
+ }
200
+ // Check if posts or terms should be updated
201
+ else if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
202
+ return Permalink_Manager_URI_Functions_Tax::update_all_permalinks();
203
+ } else {
204
+ return Permalink_Manager_URI_Functions_Post::update_all_permalinks();
205
+ }
206
  }
207
 
208
  /**
254
  foreach($group as $element => $permastruct) {
255
  // Trim slashes
256
  $permastruct = trim($permastruct, "/");
 
 
 
 
257
  }
 
 
258
  } else {
259
  unset($new_options[$group_name]);
260
  }
261
  }
262
 
263
  // Override the global with settings
 
264
  $permalink_manager_permastructs = $new_options;
265
 
266
  // Save the settings in database
280
  $removed_uris = 0;
281
  $removed_redirects = 0;
282
 
283
+ // Get all element IDs
284
+ $element_ids = array_merge(array_keys((array) $permalink_manager_uris), array_keys((array) $permalink_manager_redirects));
285
+
286
+ // 1. Remove unused custom URI & redirects for deleted post or term
287
+ foreach($element_ids as $element_id) {
288
  $count = self::clear_single_element_uris_and_redirects($element_id, true);
289
 
290
  $removed_uris = (!empty($count[0])) ? $count[0] + $removed_uris : $removed_uris;
291
  $removed_redirects = (!empty($count[1])) ? $count[1] + $removed_redirects : $removed_redirects;
292
  }
293
 
294
+ // 2. Keep only a single redirect (make it unique)
295
+ $removed_redirects += self::clear_redirects_array(true);
296
+
297
+ // 3. Optional method to keep the permalinks unique
298
+ if(apply_filters('permalink_manager_fix_uri_duplicates', false) == true) {
299
+ self::fix_uri_duplicates();
300
+ }
301
+
302
  // Save cleared URIs & Redirects
303
  if($removed_uris > 0 || $removed_redirects > 0) {
304
  update_option('permalink-manager-uris', array_filter($permalink_manager_uris));
305
  update_option('permalink-manager-redirects', array_filter($permalink_manager_redirects));
306
 
307
+ $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(sprintf(__( '%d Custom URIs and %d Custom Redirects were removed!', 'permalink-manager' ), $removed_uris, $removed_redirects), 'updated updated_slugs');
308
  } else {
309
+ $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(__( 'No Custom URIs or Custom Redirects were removed!', 'permalink-manager' ), 'error updated_slugs');
310
  }
311
  }
312
 
399
  }
400
  }
401
 
402
+ /**
403
+ * Make the redirects unique
404
+ */
405
+ public static function clear_redirects_array($count_removed = false) {
406
+ global $permalink_manager_redirects;
407
+
408
+ $removed_redirects = 0;
409
+
410
+ $all_redirect_duplicates = Permalink_Manager_Helper_Functions::get_all_duplicates(true);
411
+
412
+ foreach($all_redirect_duplicates as $single_redirect_duplicate) {
413
+
414
+ $last_element = end($single_redirect_duplicate);
415
+ foreach($single_redirect_duplicate as $redirect_key) {
416
+ // Keep a single redirect
417
+ if($last_element == $redirect_key) { continue; }
418
+ preg_match("/redirect-([\d]+)_([\d]+)/", $redirect_key, $ids);
419
+
420
+ if(!empty($ids[2]) && !empty($permalink_manager_redirects[$ids[2]][$ids[1]])) {
421
+ $removed_redirects++;
422
+ unset($permalink_manager_redirects[$ids[2]][$ids[1]]);
423
+ }
424
+ }
425
+ }
426
+
427
+ // Check if function should only return the counts or update
428
+ if($count_removed) {
429
+ return $removed_redirects;
430
+ } else if(isset($duplicated_redirect_id)) {
431
+ update_option('permalink-manager-redirects', array_filter($permalink_manager_redirects));
432
+ return true;
433
+ }
434
+ }
435
+
436
  /**
437
  * Remove custom URI & redirects for any requested post or term
438
  */
479
  }
480
 
481
  /**
482
+ * Keep the permalinks unique
483
+ */
484
+ public static function fix_uri_duplicates() {
485
+ global $permalink_manager_uris;
 
 
 
 
 
 
486
 
487
+ $duplicates = array_count_values($permalink_manager_uris);
 
 
 
 
 
 
 
 
 
 
488
 
489
+ foreach($duplicates as $uri => $count) {
490
+ if($count == 1) { continue; }
491
+
492
+ $ids = array_keys($permalink_manager_uris, $uri);
493
+ foreach($ids as $index => $id) {
494
+ $permalink_manager_uris[$id] = ($index > 0) ? "{$uri}-{$index}" : $uri;
495
+ }
 
 
496
  }
497
+
498
+ update_option('permalink-manager-uris', $permalink_manager_uris);
499
  }
500
 
501
  /**
includes/core/permalink-manager-admin-functions.php CHANGED
@@ -6,7 +6,6 @@
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() {
@@ -41,7 +40,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
41
  global $active_section, $active_subsection, $current_admin_tax;
42
 
43
  // 1. Get current section
44
- if(isset($_GET['page']) && $_GET['page'] == $this->plugin_slug) {
45
  if(isset($_POST['section'])) {
46
  $this->active_section = $_POST['section'];
47
  } else if(isset($_GET['section'])) {
@@ -80,7 +79,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
80
  * Add menu page.
81
  */
82
  public function add_menu_page() {
83
- $this->menu_name = add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', $this->plugin_slug, array($this, 'display_section') );
84
 
85
  add_action( 'admin_init', array($this, 'enqueue_styles' ) );
86
  add_action( 'admin_init', array($this, 'enqueue_scripts' ) );
@@ -101,20 +100,23 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
101
  wp_enqueue_script( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.js', array( 'jquery', ), PERMALINK_MANAGER_VERSION, false );
102
  wp_enqueue_script( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery', 'permalink-manager-plugins' ), PERMALINK_MANAGER_VERSION, false );
103
 
104
- wp_localize_script( 'permalink-manager', 'permalink_manager', array('ajax_url' => admin_url('admin-ajax.php'), 'url' => PERMALINK_MANAGER_URL) );
105
 
106
  }
107
 
108
  /**
109
- * Get admin url for the plugin
110
- */
111
- function get_admin_url($append = '') {
112
- return menu_page_url( "{$this->plugin_slug}", false ) . $append;
 
 
 
113
  }
114
 
115
  /**
116
- * Additional links on "Plugins" page
117
- */
118
  public function plugins_page_links($links) {
119
  $links[] = sprintf('<a href="%s">%s</a>', $this->get_admin_url(), __( 'URI Editor', 'permalink-manager' ));
120
  if(!defined('PERMALINK_MANAGER_PRO')) {
@@ -385,7 +387,10 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
385
  $html .= ($wrap) ? "</table>" : "";
386
 
387
  // End the fields' section + add button & nonce fields
388
- $html .= ($nonce_action && $nonce_name) ? wp_nonce_field($nonce_action, $nonce_name, true, true) : "";
 
 
 
389
  $html .= ($button_text) ? get_submit_button($button_text, $button_class, '', false, $button_attributes) : "";
390
  $html .= '</form>';
391
  $html .= ($form_column_class) ? "</div>" : "";
@@ -483,12 +488,6 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
483
  return $html;
484
  }
485
 
486
- static function pro_text($text_only = false) {
487
- $text = sprintf(__('This functionality is available only in <a href="%s" target="_blank">Permalink Manager Pro</a>.', 'permalink-manager'), PERMALINK_MANAGER_WEBSITE);
488
-
489
- return ($text_only) ? $text : sprintf("<div class=\"alert info\"> %s</div>", wpautop($text, 'alert', false));
490
- }
491
-
492
  /**
493
  * Help tooltip
494
  */
@@ -500,52 +499,83 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
500
  /**
501
  * Display the table with updated slugs after one of the actions is triggered
502
  */
503
- static function display_updated_slugs($updated_array, $uri_type = 'post') {
504
- // Check if slugs should be displayed
505
- $first_slug = reset($updated_array);
506
-
507
- $header_footer = '<tr>';
508
- $header_footer .= '<th class="column-primary">' . __('Title', 'permalink-manager') . '</th>';
509
- $header_footer .= '<th>' . __('Old URI', 'permalink-manager') . '</th>';
510
- $header_footer .= '<th>' . __('New URI', 'permalink-manager') . '</th>';
511
- $header_footer .= (isset($first_slug['old_slug'])) ? '<th>' . __('Old Slug', 'permalink-manager') . '</th>' : "";
512
- $header_footer .= (isset($first_slug['new_slug'])) ? '<th>' . __('New Slug', 'permalink-manager') . '</th>' : "";
513
- $header_footer .= '</tr>';
514
 
515
  $updated_slugs_count = 0;
516
- $main_content = "";
517
- foreach($updated_array as $row) {
518
- // Odd/even class
519
- $updated_slugs_count++;
520
- $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
521
-
522
- // Taxonomy
523
- if(!empty($row['tax'])) {
524
- $term_link = get_term_link(intval($row['ID']), $row['tax']);
525
- $permalink = (is_wp_error($term_link)) ? "-" : $term_link;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  } else {
527
- $permalink = get_permalink($row['ID']);
528
  }
529
 
530
- // Decode permalink
531
- $permalink = urldecode(urldecode($permalink));
 
 
 
 
 
 
532
 
533
- $main_content .= "<tr{$alternate_class}>";
534
- $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['item_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>';
535
- $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . urldecode($row['old_uri']) . '</td>';
536
- $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . urldecode($row['new_uri']) . '</td>';
537
- $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . urldecode($row['old_slug']) . '</td>' : "";
538
- $main_content .= (isset($row['new_slug'])) ? '<td data-colname="' . __('New Slug', 'permalink-manager') . '">' . urldecode($row['new_slug']) . '</td>' : "";
539
- $main_content .= '</tr>';
540
  }
541
 
542
- // Merge header, footer and content
543
- $html = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
544
- $html .= '<table class="widefat wp-list-table updated-slugs-table">';
545
- $html .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
546
- $html .= '</table>';
 
 
547
 
548
- return $html;
 
549
  }
550
 
551
  /**
@@ -580,6 +610,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
580
 
581
  if(!empty($element->ID)) {
582
  $id = $element_id = $element->ID;
 
583
 
584
  // Auto-update settings
585
  $auto_update_val = get_post_meta($id, "auto_update_uri", true);
@@ -593,6 +624,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
593
  } else {
594
  $id = $element->term_id;
595
  $element_id = "tax-{$id}";
 
596
  }
597
 
598
  // Decode default URI
@@ -624,9 +656,20 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
624
  $custom_uri_field
625
  );
626
 
 
 
 
 
 
 
 
 
 
 
 
627
  // Three fields that should be hidden on front-page
628
  if(get_option('page_on_front') != $id) {
629
- // 5. Auto-update URI
630
  if(!empty($auto_update_choices)) {
631
  $html .= sprintf("<div><label for=\"auto_auri\" class=\"strong\">%s %s</label><span>%s</span></div>",
632
  __("Auto-update the URI", "permalink-manager"),
@@ -635,14 +678,14 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
635
  );
636
  }
637
 
638
- // 6. Default URI
639
  $html .= sprintf(
640
  "<div class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></div>",
641
  __("Default URI", "permalink-manager"), esc_html($default_uri),
642
  __("Restore to Default URI", "permalink-manager")
643
  );
644
 
645
- // 7. Native URI info
646
  if(!empty($permalink_manager_options['general']['redirect']) && ((!empty($element->post_status) && in_array($element->post_status, array('auto-draft', 'trash', 'draft'))) == false)) {
647
  $native_permalink = trim(Permalink_Manager_Helper_Functions::get_permalink_base($element), "/") . "/";
648
  $native_permalink .= $native_uri;
@@ -656,7 +699,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
656
  }
657
  }
658
 
659
- // 8. Custom redirects
660
  $html .= ($element->ID) ? self::display_redirect_panel($id) : self::display_redirect_panel("tax-{$id}");
661
 
662
  $html .= "</div>";
@@ -685,7 +728,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
685
  $html .= "<div id=\"redirect-panel-inside\">";
686
 
687
  // Table
688
- if(class_exists('Permalink_Manager_Pro_Addons')) {
689
  $html .= Permalink_Manager_Pro_Addons::display_redirect_form($element_id);
690
  } else {
691
  $html .= self::pro_text(true);
@@ -782,4 +825,36 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
782
  die();
783
  }
784
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
785
  }
6
  class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
7
 
8
  public $menu_name, $sections, $active_section, $active_subsection;
 
9
  public $plugin_basename = PERMALINK_MANAGER_BASENAME;
10
 
11
  public function __construct() {
40
  global $active_section, $active_subsection, $current_admin_tax;
41
 
42
  // 1. Get current section
43
+ if(isset($_GET['page']) && $_GET['page'] == PERMALINK_MANAGER_PLUGIN_SLUG) {
44
  if(isset($_POST['section'])) {
45
  $this->active_section = $_POST['section'];
46
  } else if(isset($_GET['section'])) {
79
  * Add menu page.
80
  */
81
  public function add_menu_page() {
82
+ $this->menu_name = add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', PERMALINK_MANAGER_PLUGIN_SLUG, array($this, 'display_section') );
83
 
84
  add_action( 'admin_init', array($this, 'enqueue_styles' ) );
85
  add_action( 'admin_init', array($this, 'enqueue_scripts' ) );
100
  wp_enqueue_script( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.js', array( 'jquery', ), PERMALINK_MANAGER_VERSION, false );
101
  wp_enqueue_script( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery', 'permalink-manager-plugins' ), PERMALINK_MANAGER_VERSION, false );
102
 
103
+ wp_localize_script( 'permalink-manager', 'permalink_manager', array('ajax_url' => admin_url('admin-ajax.php'), 'url' => PERMALINK_MANAGER_URL, 'spinners' => admin_url('images')) );
104
 
105
  }
106
 
107
  /**
108
+ * Get admin url for the plugin
109
+ */
110
+ public static function get_admin_url($append = '') {
111
+ //return menu_page_url(PERMALINK_MANAGER_PLUGIN_SLUG, false) . $append;
112
+ $admin_page = sprintf("tools.php?page=%s", PERMALINK_MANAGER_PLUGIN_SLUG . $append);
113
+
114
+ return admin_url($admin_page);
115
  }
116
 
117
  /**
118
+ * Additional links on "Plugins" page
119
+ */
120
  public function plugins_page_links($links) {
121
  $links[] = sprintf('<a href="%s">%s</a>', $this->get_admin_url(), __( 'URI Editor', 'permalink-manager' ));
122
  if(!defined('PERMALINK_MANAGER_PRO')) {
387
  $html .= ($wrap) ? "</table>" : "";
388
 
389
  // End the fields' section + add button & nonce fields
390
+ if($nonce_action && $nonce_name) {
391
+ $html .= wp_nonce_field($nonce_action, $nonce_name, true, true);
392
+ $html .= self::generate_option_field('pm_session_id', array('value' => uniqid(), 'type' => 'hidden'));
393
+ }
394
  $html .= ($button_text) ? get_submit_button($button_text, $button_class, '', false, $button_attributes) : "";
395
  $html .= '</form>';
396
  $html .= ($form_column_class) ? "</div>" : "";
488
  return $html;
489
  }
490
 
 
 
 
 
 
 
491
  /**
492
  * Help tooltip
493
  */
499
  /**
500
  * Display the table with updated slugs after one of the actions is triggered
501
  */
502
+ static function display_updated_slugs($updated_array, $return_array = false, $display_full_table = true) {
503
+ global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
 
 
 
 
 
 
 
 
 
504
 
505
  $updated_slugs_count = 0;
506
+ $html = $main_content = $alert = "";
507
+
508
+ if(is_array($updated_array)) {
509
+ // Check if slugs should be displayed
510
+ $first_slug = reset($updated_array);
511
+
512
+ $header_footer = '<tr>';
513
+ $header_footer .= '<th class="column-primary">' . __('Title', 'permalink-manager') . '</th>';
514
+ $header_footer .= '<th>' . __('Old URI', 'permalink-manager') . '</th>';
515
+ $header_footer .= '<th>' . __('New URI', 'permalink-manager') . '</th>';
516
+ $header_footer .= (isset($first_slug['old_slug'])) ? '<th>' . __('Old Slug', 'permalink-manager') . '</th>' : "";
517
+ $header_footer .= (isset($first_slug['new_slug'])) ? '<th>' . __('New Slug', 'permalink-manager') . '</th>' : "";
518
+ $header_footer .= '</tr>';
519
+
520
+ foreach($updated_array as $row) {
521
+ // Odd/even class
522
+ $updated_slugs_count++;
523
+ $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
524
+
525
+ // Taxonomy
526
+ if(!empty($row['tax'])) {
527
+ $term_link = get_term_link(intval($row['ID']), $row['tax']);
528
+ $permalink = (is_wp_error($term_link)) ? "-" : $term_link;
529
+ } else {
530
+ $permalink = get_permalink($row['ID']);
531
+ }
532
+
533
+ // Decode permalink
534
+ $permalink = urldecode(urldecode($permalink));
535
+
536
+ $main_content .= "<tr{$alternate_class}>";
537
+ $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['item_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>';
538
+ $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . urldecode($row['old_uri']) . '</td>';
539
+ $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . urldecode($row['new_uri']) . '</td>';
540
+ $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . urldecode($row['old_slug']) . '</td>' : "";
541
+ $main_content .= (isset($row['new_slug'])) ? '<td data-colname="' . __('New Slug', 'permalink-manager') . '">' . urldecode($row['new_slug']) . '</td>' : "";
542
+ $main_content .= '</tr>';
543
+ }
544
+
545
+ // Merge header, footer and content
546
+ if($display_full_table) {
547
+ $html = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
548
+ $html .= '<table class="widefat wp-list-table updated-slugs-table">';
549
+ $html .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
550
  } else {
551
+ $html = $main_content;
552
  }
553
 
554
+ $html .= '</table>';
555
+ }
556
+
557
+ // 3. Display the alert
558
+ if(isset($updated_slugs_count)) {
559
+ if($updated_slugs_count > 0) {
560
+ $alert_content = sprintf( _n( '<strong class="updated_count">%d</strong> slug was updated!', '<strong class="updated_count">%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
561
+ $alert_content .= sprintf( __( '<a %s>Click here</a> to go to the list of updated slugs', 'permalink-manager' ), "href=\"#updated-list\"");
562
 
563
+ $alert = Permalink_Manager_Admin_Functions::get_alert_message($alert_content, 'updated updated_slugs');
564
+ } else {
565
+ $alert = Permalink_Manager_Admin_Functions::get_alert_message(__( '<strong>No slugs</strong> were updated!', 'permalink-manager' ), 'error updated_slugs');
566
+ }
 
 
 
567
  }
568
 
569
+ if($return_array) {
570
+ return array(
571
+ 'html' => $html,
572
+ 'alert' => $alert
573
+ );
574
+ } else {
575
+ $permalink_manager_before_sections_html .= $alert;
576
 
577
+ return $html;
578
+ }
579
  }
580
 
581
  /**
610
 
611
  if(!empty($element->ID)) {
612
  $id = $element_id = $element->ID;
613
+ $native_slug = $element->post_name;
614
 
615
  // Auto-update settings
616
  $auto_update_val = get_post_meta($id, "auto_update_uri", true);
624
  } else {
625
  $id = $element->term_id;
626
  $element_id = "tax-{$id}";
627
+ $native_slug = $element->slug;
628
  }
629
 
630
  // Decode default URI
656
  $custom_uri_field
657
  );
658
 
659
+ // 5. Native slug
660
+ if(!empty($element->ID) && !empty($permalink_manager_options["general"]["show_native_slug_field"])) {
661
+ $native_slug_field = Permalink_Manager_Admin_Functions::generate_option_field("native_slug", array("extra_atts" => "data-default=\"{$native_slug}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat native_slug", "value" => urldecode($native_slug)));
662
+
663
+ $html .= sprintf("<div class=\"native_slug_container\"><label for=\"native_slug\" class=\"strong\">%s %s</label><span>%s</span></div>",
664
+ __("Native slug", "permalink-manager"),
665
+ Permalink_Manager_Admin_Functions::help_tooltip(__("The native slug is by default automatically used in native permalinks (when Permalink Manager is disabled).", "permalink-manager")),
666
+ $native_slug_field
667
+ );
668
+ }
669
+
670
  // Three fields that should be hidden on front-page
671
  if(get_option('page_on_front') != $id) {
672
+ // 6. Auto-update URI
673
  if(!empty($auto_update_choices)) {
674
  $html .= sprintf("<div><label for=\"auto_auri\" class=\"strong\">%s %s</label><span>%s</span></div>",
675
  __("Auto-update the URI", "permalink-manager"),
678
  );
679
  }
680
 
681
+ // 7. Default URI
682
  $html .= sprintf(
683
  "<div class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></div>",
684
  __("Default URI", "permalink-manager"), esc_html($default_uri),
685
  __("Restore to Default URI", "permalink-manager")
686
  );
687
 
688
+ // 8. Native URI info
689
  if(!empty($permalink_manager_options['general']['redirect']) && ((!empty($element->post_status) && in_array($element->post_status, array('auto-draft', 'trash', 'draft'))) == false)) {
690
  $native_permalink = trim(Permalink_Manager_Helper_Functions::get_permalink_base($element), "/") . "/";
691
  $native_permalink .= $native_uri;
699
  }
700
  }
701
 
702
+ // 9. Custom redirects
703
  $html .= ($element->ID) ? self::display_redirect_panel($id) : self::display_redirect_panel("tax-{$id}");
704
 
705
  $html .= "</div>";
728
  $html .= "<div id=\"redirect-panel-inside\">";
729
 
730
  // Table
731
+ if(Permalink_Manager_Admin_Functions::is_pro_active()) {
732
  $html .= Permalink_Manager_Pro_Addons::display_redirect_form($element_id);
733
  } else {
734
  $html .= self::pro_text(true);
825
  die();
826
  }
827
 
828
+ /**
829
+ * Check if Permalink Manager Pro is active
830
+ */
831
+ public static function is_pro_active($return_text = false) {
832
+ if(defined('PERMALINK_MANAGER_PRO') && PERMALINK_MANAGER_PRO == true) {
833
+ $is_pro = true;
834
+ } else {
835
+ $is_pro = false;
836
+ }
837
+
838
+ // Check if license is active
839
+ if(class_exists('Permalink_Manager_Pro_Functions')) {
840
+ $exp_date = Permalink_Manager_Pro_Functions::get_expiration_date(true);
841
+
842
+ $is_pro = ($exp_date > 0) ? false : true;
843
+ } else {
844
+ $is_pro = false;
845
+ }
846
+
847
+ return $is_pro;
848
+ }
849
+
850
+ static function pro_text($text_only = false) {
851
+ if(class_exists('Permalink_Manager_Pro_Functions')) {
852
+ $text = Permalink_Manager_Pro_Functions::get_expiration_date(false, true);
853
+ } else {
854
+ $text = sprintf(__('This functionality is available only in <a href="%s" target="_blank">Permalink Manager Pro</a>.', 'permalink-manager'), PERMALINK_MANAGER_WEBSITE);
855
+ }
856
+
857
+ return ($text_only) ? $text : sprintf("<div class=\"alert info\"> %s</div>", wpautop($text, 'alert', false));
858
+ }
859
+
860
  }
includes/core/permalink-manager-core-functions.php CHANGED
@@ -13,13 +13,13 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
13
  global $permalink_manager_options;
14
 
15
  // Trigger only in front-end
16
- if(!is_admin()) {
17
  // Use the URIs set in this plugin
18
  add_filter( 'request', array($this, 'detect_post'), 0, 1 );
19
 
20
  // Redirect from old URIs to new URIs + adjust canonical redirect settings
21
  add_action( 'template_redirect', array($this, 'new_uri_redirect_and_404'), 1);
22
- add_action( 'wp', array($this, 'adjust_canonical_redirect'), 0, 1);
23
 
24
  // Case insensitive permalinks
25
  if(!empty($permalink_manager_options['general']['case_insensitive_permalinks'])) {
@@ -44,11 +44,11 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
44
  /**
45
  * The most important Permalink Manager function
46
  */
47
- function detect_post($query) {
48
  global $wpdb, $wp, $wp_rewrite, $permalink_manager_uris, $wp_filter, $permalink_manager_options, $pm_query, $pm_uri_parts;
49
 
50
  // Check if any custom URI is used and we are not in WP-Admin dashboard
51
- if(!(is_array($permalink_manager_uris)) || empty($query)) return $query;
52
 
53
  // Used in debug mode & endpoints
54
  $old_query = $query;
@@ -56,7 +56,10 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
56
  /**
57
  * 1. Prepare URL and check if it is correct (make sure that both requested URL & home_url share the same protoocl and get rid of www prefix)
58
  */
59
- $request_url = sprintf("http://%s%s", str_replace("www.", "", $_SERVER['HTTP_HOST']), strtok($_SERVER['REQUEST_URI'], "?"));
 
 
 
60
  $raw_home_url = trim(get_option('home'));
61
  $home_url = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $raw_home_url);
62
 
@@ -216,8 +219,12 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
216
  }
217
  }
218
 
219
- // Alter query parameters
220
- if($post_type == 'page') {
 
 
 
 
221
  $query['pagename'] = $final_uri;
222
  } else if($post_type == 'post') {
223
  $query['name'] = $final_uri;
@@ -252,8 +259,12 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
252
  /**
253
  * 5A. Endpoints
254
  */
255
- if(!empty($element_id) && ((!empty($endpoint)) || !empty($endpoint_value))) {
256
- if($endpoint == 'feed') {
 
 
 
 
257
  $query[$endpoint] = 'feed';
258
  } else if($endpoint == 'page') {
259
  $endpoint = 'paged';
@@ -329,7 +340,13 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
329
  wp_die($debug_txt);
330
  }
331
 
332
- return $query;
 
 
 
 
 
 
333
  }
334
 
335
  /**
@@ -418,11 +435,19 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
418
  $trailing_slashes_mode = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : false;
419
  $trailing_slashes_redirect_mode = (!empty($permalink_manager_options['general']['trailing_slashes_redirect'])) ? $permalink_manager_options['general']['trailing_slashes_redirect'] : 301;
420
 
421
- // Get query string
422
  $query_string = $_SERVER['QUERY_STRING'];
 
423
 
424
  // Get home URL
425
  $home_url = rtrim(get_option('home'), "/");
 
 
 
 
 
 
 
426
 
427
  /**
428
  * 1A. External redirect
@@ -431,6 +456,9 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
431
  $external_url = $permalink_manager_external_redirects[$pm_query['id']];
432
 
433
  if(filter_var($external_url, FILTER_VALIDATE_URL)) {
 
 
 
434
  wp_redirect($external_url, 301);
435
  exit();
436
  }
@@ -442,9 +470,12 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
442
  if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request) && !empty($pm_query['uri'])) {
443
  $uri = $pm_query['uri'];
444
 
 
 
 
445
  // Check if the URI is not assigned to any post/term's redirects
446
  foreach($permalink_manager_redirects as $element => $redirects) {
447
- if(is_array($redirects) && in_array($uri, $redirects)) {
448
 
449
  // Post is detected
450
  if(is_numeric($element)) {
@@ -493,15 +524,6 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
493
  * 2. Check trailing slashes (ignore links with query parameters)
494
  */
495
  if($trailing_slashes_mode && empty($_SERVER['QUERY_STRING']) && !empty($_SERVER['REQUEST_URI'])) {
496
- $home_dir = parse_url($home_url, PHP_URL_PATH);
497
- $old_uri = $_SERVER['REQUEST_URI'];
498
-
499
- // Fix for WP installed in directories (remove the directory name from the URI)
500
- if(!empty($home_dir)) {
501
- $home_dir_regex = preg_quote(trim($home_dir), "/");
502
- $old_uri = preg_replace("/{$home_dir_regex}/", "", $old_uri, 1);
503
- }
504
-
505
  // Check if $old_uri ends with slash or not
506
  $ends_with_slash = (substr($old_uri, -1) == "/") ? true : false;
507
  $trailing_slashes_mode = (preg_match("/.*\.([a-zA-Z]{3,4})\/?$/", $old_uri) && $trailing_slashes_mode == 10) ? 20 : $trailing_slashes_mode;
@@ -529,10 +551,21 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
529
  }
530
  }
531
 
 
 
 
 
 
 
 
 
532
  /**
533
  * 3. Ignore default URIs (or do nothing if redirects are disabled)
534
  */
535
  if(!empty($correct_permalink) && !empty($redirect_mode)) {
 
 
 
536
  // Append query string
537
  $correct_permalink = (!empty($query_string)) ? "{$correct_permalink}?{$query_string}" : $correct_permalink;
538
 
@@ -575,11 +608,13 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
575
  $custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : "";
576
  }
577
 
578
- if(empty($custom_uri) && !empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
 
579
 
580
  if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) {
581
  remove_action('template_redirect', 'redirect_canonical');
582
  add_filter('wpml_is_redirected', '__return_false', 99, 2);
 
583
  }
584
  }
585
 
13
  global $permalink_manager_options;
14
 
15
  // Trigger only in front-end
16
+ if(!is_admin() && function_exists('is_customize_preview') && !is_customize_preview()) {
17
  // Use the URIs set in this plugin
18
  add_filter( 'request', array($this, 'detect_post'), 0, 1 );
19
 
20
  // Redirect from old URIs to new URIs + adjust canonical redirect settings
21
  add_action( 'template_redirect', array($this, 'new_uri_redirect_and_404'), 1);
22
+ add_action( 'parse_query', array($this, 'adjust_canonical_redirect'), 0, 1);
23
 
24
  // Case insensitive permalinks
25
  if(!empty($permalink_manager_options['general']['case_insensitive_permalinks'])) {
44
  /**
45
  * The most important Permalink Manager function
46
  */
47
+ public static function detect_post($query, $request_url = false, $return_object = false) {
48
  global $wpdb, $wp, $wp_rewrite, $permalink_manager_uris, $wp_filter, $permalink_manager_options, $pm_query, $pm_uri_parts;
49
 
50
  // Check if any custom URI is used and we are not in WP-Admin dashboard
51
+ if(!(is_array($permalink_manager_uris)) || (empty($query) && empty($request_url))) return $query;
52
 
53
  // Used in debug mode & endpoints
54
  $old_query = $query;
56
  /**
57
  * 1. Prepare URL and check if it is correct (make sure that both requested URL & home_url share the same protoocl and get rid of www prefix)
58
  */
59
+ $request_url = (!empty($request_url)) ? parse_url($request_url, PHP_URL_PATH) : $_SERVER['REQUEST_URI'];
60
+ $request_url = strtok($request_url, "?");
61
+
62
+ $request_url = sprintf("http://%s%s", str_replace("www.", "", $_SERVER['HTTP_HOST']), $request_url);
63
  $raw_home_url = trim(get_option('home'));
64
  $home_url = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $raw_home_url);
65
 
219
  }
220
  }
221
 
222
+ // Alter query parameters + support drafts URLs
223
+ if($post_to_load->post_status == 'draft') {
224
+ $query['p'] = $element_id;
225
+ $query['preview'] = true;
226
+ $query['post_type'] = $post_type;
227
+ } else if($post_type == 'page') {
228
  $query['pagename'] = $final_uri;
229
  } else if($post_type == 'post') {
230
  $query['name'] = $final_uri;
259
  /**
260
  * 5A. Endpoints
261
  */
262
+ if(!empty($element_id) && (!empty($endpoint) || !empty($endpoint_value))) {
263
+ if(is_array($endpoint)) {
264
+ foreach($endpoint as $endpoint_name => $endpoint_value) {
265
+ $query[$endpoint_name] = $endpoint_value;
266
+ }
267
+ } else if($endpoint == 'feed') {
268
  $query[$endpoint] = 'feed';
269
  } else if($endpoint == 'page') {
270
  $endpoint = 'paged';
340
  wp_die($debug_txt);
341
  }
342
 
343
+ if($return_object && !empty($term)) {
344
+ return $term;
345
+ } else if($return_object && !empty($post_to_load)) {
346
+ return $post_to_load;
347
+ } else {
348
+ return $query;
349
+ }
350
  }
351
 
352
  /**
435
  $trailing_slashes_mode = (!empty($permalink_manager_options['general']['trailing_slashes'])) ? $permalink_manager_options['general']['trailing_slashes'] : false;
436
  $trailing_slashes_redirect_mode = (!empty($permalink_manager_options['general']['trailing_slashes_redirect'])) ? $permalink_manager_options['general']['trailing_slashes_redirect'] : 301;
437
 
438
+ // Get query string & URI
439
  $query_string = $_SERVER['QUERY_STRING'];
440
+ $old_uri = $_SERVER['REQUEST_URI'];
441
 
442
  // Get home URL
443
  $home_url = rtrim(get_option('home'), "/");
444
+ $home_dir = parse_url($home_url, PHP_URL_PATH);
445
+
446
+ // Fix for WP installed in directories (remove the directory name from the URI)
447
+ if(!empty($home_dir)) {
448
+ $home_dir_regex = preg_quote(trim($home_dir), "/");
449
+ $old_uri = preg_replace("/{$home_dir_regex}/", "", $old_uri, 1);
450
+ }
451
 
452
  /**
453
  * 1A. External redirect
456
  $external_url = $permalink_manager_external_redirects[$pm_query['id']];
457
 
458
  if(filter_var($external_url, FILTER_VALIDATE_URL)) {
459
+ // Allow redirect
460
+ $wp_query->query_vars['do_not_redirect'] = 0;
461
+
462
  wp_redirect($external_url, 301);
463
  exit();
464
  }
470
  if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request) && !empty($pm_query['uri'])) {
471
  $uri = $pm_query['uri'];
472
 
473
+ // Make sure that URIs with non-ASCII characters are also detected
474
+ $decoded_url = urldecode($uri);
475
+
476
  // Check if the URI is not assigned to any post/term's redirects
477
  foreach($permalink_manager_redirects as $element => $redirects) {
478
+ if(is_array($redirects) && (in_array($uri, $redirects) || in_array($decoded_url, $redirects))) {
479
 
480
  // Post is detected
481
  if(is_numeric($element)) {
524
  * 2. Check trailing slashes (ignore links with query parameters)
525
  */
526
  if($trailing_slashes_mode && empty($_SERVER['QUERY_STRING']) && !empty($_SERVER['REQUEST_URI'])) {
 
 
 
 
 
 
 
 
 
527
  // Check if $old_uri ends with slash or not
528
  $ends_with_slash = (substr($old_uri, -1) == "/") ? true : false;
529
  $trailing_slashes_mode = (preg_match("/.*\.([a-zA-Z]{3,4})\/?$/", $old_uri) && $trailing_slashes_mode == 10) ? 20 : $trailing_slashes_mode;
551
  }
552
  }
553
 
554
+ /**
555
+ * 3. Check if URL contains duplicated slashes
556
+ */
557
+ if(!empty($old_uri) && ($old_uri != '/') && preg_match('/\/{2,}/', $old_uri)) {
558
+ $new_uri = ltrim(preg_replace('/\/{2,}/', '/', $old_uri), "/");
559
+ $correct_permalink = "{$home_url}/{$new_uri}";
560
+ }
561
+
562
  /**
563
  * 3. Ignore default URIs (or do nothing if redirects are disabled)
564
  */
565
  if(!empty($correct_permalink) && !empty($redirect_mode)) {
566
+ // Allow redirect
567
+ $wp_query->query_vars['do_not_redirect'] = 0;
568
+
569
  // Append query string
570
  $correct_permalink = (!empty($query_string)) ? "{$correct_permalink}?{$query_string}" : $correct_permalink;
571
 
608
  $custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : "";
609
  }
610
 
611
+ //if(empty($custom_uri) && !empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
612
+ if(!empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
613
 
614
  if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) {
615
  remove_action('template_redirect', 'redirect_canonical');
616
  add_filter('wpml_is_redirected', '__return_false', 99, 2);
617
+ add_filter('pll_check_canonical_url', '__return_false', 99, 2);
618
  }
619
  }
620
 
includes/core/permalink-manager-helper-functions.php CHANGED
@@ -5,7 +5,15 @@
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()
@@ -110,7 +118,7 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
110
  $term_slug = "{$term_slug}/{$last_term_slug}";
111
  }
112
  // C. Force flat taxonomy base - get highgest level term (if %taxonomy_flat% tag is used)
113
- else if($mode == 3) {
114
  foreach($terms as $single_term) {
115
  if($single_term->parent == 0) {
116
  $term_slug = self::force_custom_slugs($single_term->slug, $single_term);
@@ -284,8 +292,10 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
284
  static function get_endpoints() {
285
  global $wp_rewrite;
286
 
 
 
287
  // Start with default endpoints
288
- $endpoints = "page|feed|embed|attachment|trackback|filter";
289
 
290
  if(!empty($wp_rewrite->endpoints)) {
291
  foreach($wp_rewrite->endpoints as $endpoint) {
@@ -419,7 +429,7 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
419
 
420
  // $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $clean);
421
  $percent_sign = ($keep_percent_sign) ? "\%" : "";
422
- $clean = preg_replace("/[^\p{L}a-zA-Z0-9{$percent_sign}\/_\.|+ -]/u", '', $clean);
423
  $clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-');
424
 
425
  // Remove special characters
@@ -433,6 +443,17 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
433
  return $clean;
434
  }
435
 
 
 
 
 
 
 
 
 
 
 
 
436
  /**
437
  * Force custom slugs
438
  */
@@ -443,7 +464,7 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
443
  $title = (!empty($object->name)) ? $object->name : $object->post_title;
444
 
445
  $old_slug = basename($slug);
446
- $new_slug = self::sanitize_title($title, false);
447
 
448
  $slug = ($old_slug != $new_slug) ? str_replace($old_slug, $new_slug, $slug) : $slug;
449
  }
@@ -471,11 +492,11 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
471
  /**
472
  * Detect duplicates
473
  */
474
- public static function get_all_duplicates() {
475
  global $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_options, $wpdb;
476
 
477
  // Make sure that both variables are arrays
478
- $all_uris = (is_array($permalink_manager_uris)) ? $permalink_manager_uris : array();
479
  $permalink_manager_redirects = (is_array($permalink_manager_redirects)) ? $permalink_manager_redirects : array();
480
 
481
  // Convert redirects list, so it can be merged with $permalink_manager_uris
@@ -521,4 +542,28 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
521
  return (in_array($uri, $permalink_manager_uris)) ? 1 : 0;
522
  }
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  }
5
  */
6
  class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
7
 
8
+ public function __construct() {
9
+ add_action('plugins_loaded', array($this, 'init'), 5);
10
+ }
11
+
12
+ public function init() {
13
+ // Clear the final default URIs
14
+ add_filter( 'permalink_manager_filter_default_term_uri', array('Permalink_Manager_Helper_Functions', 'clear_single_uri'), 20);
15
+ add_filter( 'permalink_manager_filter_default_post_uri', array('Permalink_Manager_Helper_Functions', 'clear_single_uri'), 20);
16
+ }
17
 
18
  /**
19
  * Support for multidimensional arrays - array_map()
118
  $term_slug = "{$term_slug}/{$last_term_slug}";
119
  }
120
  // C. Force flat taxonomy base - get highgest level term (if %taxonomy_flat% tag is used)
121
+ else if($mode == 4) {
122
  foreach($terms as $single_term) {
123
  if($single_term->parent == 0) {
124
  $term_slug = self::force_custom_slugs($single_term->slug, $single_term);
292
  static function get_endpoints() {
293
  global $wp_rewrite;
294
 
295
+ $pagination_endpoint = (!empty($wp_rewrite->pagination_base)) ? $wp_rewrite->pagination_base : 'page';
296
+
297
  // Start with default endpoints
298
+ $endpoints = "{$pagination_endpoint}|feed|embed|attachment|trackback|filter";
299
 
300
  if(!empty($wp_rewrite->endpoints)) {
301
  foreach($wp_rewrite->endpoints as $endpoint) {
429
 
430
  // $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $clean);
431
  $percent_sign = ($keep_percent_sign) ? "\%" : "";
432
+ $clean = preg_replace("/[^\p{Thai}\p{Xwd}a-zA-Z0-9{$percent_sign}\/_\.|+ -]/u", '', $clean);
433
  $clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-');
434
 
435
  // Remove special characters
443
  return $clean;
444
  }
445
 
446
+ /**
447
+ * Clear the URI
448
+ */
449
+ public static function clear_single_uri($uri) {
450
+ $uri = preg_replace('/\s+/', '', $uri);
451
+ $uri = str_replace('//', '/', $uri);
452
+ $uri = trim($uri, "/");
453
+
454
+ return $uri;
455
+ }
456
+
457
  /**
458
  * Force custom slugs
459
  */
464
  $title = (!empty($object->name)) ? $object->name : $object->post_title;
465
 
466
  $old_slug = basename($slug);
467
+ $new_slug = self::sanitize_title($title, false, null, true);
468
 
469
  $slug = ($old_slug != $new_slug) ? str_replace($old_slug, $new_slug, $slug) : $slug;
470
  }
492
  /**
493
  * Detect duplicates
494
  */
495
+ public static function get_all_duplicates($include_custom_uris = true) {
496
  global $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_options, $wpdb;
497
 
498
  // Make sure that both variables are arrays
499
+ $all_uris = ($include_custom_uris && is_array($permalink_manager_uris)) ? $permalink_manager_uris : array();
500
  $permalink_manager_redirects = (is_array($permalink_manager_redirects)) ? $permalink_manager_redirects : array();
501
 
502
  // Convert redirects list, so it can be merged with $permalink_manager_uris
542
  return (in_array($uri, $permalink_manager_uris)) ? 1 : 0;
543
  }
544
 
545
+ /**
546
+ * URI Search
547
+ */
548
+ public static function search_uri($search_query, $content_type = null) {
549
+ global $permalink_manager_uris;
550
+
551
+ $found = array();
552
+ $search_query = preg_quote($search_query, '/');
553
+
554
+ foreach($permalink_manager_uris as $id => $uri) {
555
+ if(preg_match("/\b$search_query\b/i", $uri)) {
556
+ if($content_type && $content_type == 'taxonomies' && (strpos($id, 'tax-') !== false)) {
557
+ $found[] = (int) abs(filter_var($id, FILTER_SANITIZE_NUMBER_INT));
558
+ } else if($content_type && $content_type == 'posts' && is_numeric($id)) {
559
+ $found[] = (int) filter_var($id, FILTER_SANITIZE_NUMBER_INT);
560
+ } else {
561
+ $found[] = $id;
562
+ }
563
+ }
564
+ }
565
+
566
+ return $found;
567
+ }
568
+
569
  }
includes/core/permalink-manager-third-parties.php CHANGED
@@ -32,6 +32,11 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
32
  add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 );
33
  } else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) {
34
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9);
 
 
 
 
 
35
  }
36
 
37
  // Translate slugs
@@ -79,6 +84,22 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
79
  if(function_exists('tinv_get_option')) {
80
  add_filter('permalink-manager-detect-uri', array($this, 'ti_woocommerce_wishlist_uris'), 15, 3);
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  /**
@@ -176,11 +197,15 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
176
  }
177
 
178
  // Fix for multidomain language configuration
179
- if(!empty($polylang->options['force_lang']) && $polylang->options['force_lang'] == 3) {
180
- $domains = (array) $polylang->options['domains'];
 
 
 
 
181
 
182
  foreach($domains as &$domain) {
183
- $domain = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $domain);
184
  }
185
 
186
  $request_url = trim(str_replace($domains, "", $request_url), "/");
@@ -254,6 +279,21 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
254
  return $base;
255
  }
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) {
258
  $post = (is_integer($element)) ? get_post($element) : $element;
259
  $language_code = self::wpml_get_language_code($post);
@@ -455,7 +495,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
455
  }
456
 
457
  // Do not redirect "thank you" & another WooCommerce pages
458
- if(is_checkout() || is_wc_endpoint_url()) {
459
  $wp_query->query_vars['do_not_redirect'] = 1;
460
  }
461
  }
@@ -509,5 +549,149 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
509
  return $uri_parts;
510
  }
511
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
  ?>
32
  add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 );
33
  } else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) {
34
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9);
35
+
36
+ // Append query parameter
37
+ add_filter('permalink_manager_filter_final_term_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
38
+ add_filter('permalink_manager_filter_final_post_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
39
+ add_filter('permalink_manager_filter_post_sample_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
40
  }
41
 
42
  // Translate slugs
84
  if(function_exists('tinv_get_option')) {
85
  add_filter('permalink-manager-detect-uri', array($this, 'ti_woocommerce_wishlist_uris'), 15, 3);
86
  }
87
+
88
+ // 9. Revisionize
89
+ if(defined('REVISIONIZE_ROOT')) {
90
+ add_action('revisionize_after_create_revision', array($this, 'revisionize_keep_post_uri'), 9, 2);
91
+ add_action('revisionize_before_publish', array($this,'revisionize_clone_uri'), 9, 2);
92
+ }
93
+
94
+ // 10. WP All Import
95
+ if(class_exists('PMXI_Plugin')) {
96
+ add_action('pmxi_extend_options_featured', array($this, 'wpaiextra_uri_display'), 9, 2);
97
+ add_filter('pmxi_options_options', array($this, 'wpai_api_options'));
98
+ add_filter('pmxi_addons', array($this, 'wpai_api_register'));
99
+ add_filter('wp_all_import_addon_parse', array($this, 'wpai_api_parse'));
100
+ add_filter('wp_all_import_addon_import', array($this, 'wpai_api_import'));
101
+ add_action('pmxi_saved_post', array($this, 'wpai_save_redirects'));
102
+ }
103
  }
104
 
105
  /**
197
  }
198
 
199
  // Fix for multidomain language configuration
200
+ if((isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 2) || (!empty($polylang->options['force_lang']) && $polylang->options['force_lang'] == 3)) {
201
+ if(!empty($polylang->options['domains'])) {
202
+ $domains = (array) $polylang->options['domains'];
203
+ } else if(!empty($sitepress_settings['language_domains'])) {
204
+ $domains = (array) $sitepress_settings['language_domains'];
205
+ }
206
 
207
  foreach($domains as &$domain) {
208
+ $domain = preg_replace("/(http(s)?:\/\/(www\.)?)?(.+?)\/?$/", "http://$4", $domain);
209
  }
210
 
211
  $request_url = trim(str_replace($domains, "", $request_url), "/");
279
  return $base;
280
  }
281
 
282
+ function wpml_append_lang_query_parameter($permalink, $element) {
283
+ $lang = self::wpml_get_language_code($element);
284
+ $def_lang = self::get_default_language();
285
+
286
+ if(!empty($lang) && ($def_lang != $lang)) {
287
+ if(filter_var($permalink, FILTER_VALIDATE_URL)) {
288
+ $permalink = add_query_arg('lang', $lang, $permalink);
289
+ } else {
290
+ $permalink .= "?lang={$lang}";
291
+ }
292
+ }
293
+
294
+ return $permalink;
295
+ }
296
+
297
  function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) {
298
  $post = (is_integer($element)) ? get_post($element) : $element;
299
  $language_code = self::wpml_get_language_code($post);
495
  }
496
 
497
  // Do not redirect "thank you" & another WooCommerce pages
498
+ if(is_checkout() || (function_exists('is_wc_endpoint_url') && is_wc_endpoint_url())) {
499
  $wp_query->query_vars['do_not_redirect'] = 1;
500
  }
501
  }
549
  return $uri_parts;
550
  }
551
 
552
+ /**
553
+ * 9. Revisionize
554
+ */
555
+ function revisionize_keep_post_uri($old_id, $new_id) {
556
+ global $permalink_manager_uris;
557
+
558
+ // Copy the custom URI from original post and apply it to the new temp. revision post
559
+ if(!empty($permalink_manager_uris[$old_id])) {
560
+ $permalink_manager_uris[$new_id] = $permalink_manager_uris[$old_id];
561
+
562
+ update_option('permalink-manager-uris', $permalink_manager_uris);
563
+ }
564
+ }
565
+
566
+ function revisionize_clone_uri($old_id, $new_id) {
567
+ global $permalink_manager_uris;
568
+
569
+ if(!empty($permalink_manager_uris[$new_id])) {
570
+ // Copy the custom URI from revision post and apply it to the original post
571
+ $permalink_manager_uris[$old_id] = $permalink_manager_uris[$new_id];
572
+ unset($permalink_manager_uris[$new_id]);
573
+
574
+ update_option('permalink-manager-uris', $permalink_manager_uris);
575
+ }
576
+ }
577
+
578
+ /**
579
+ * 10. WP All Import
580
+ */
581
+ function wpaiextra_uri_display($post_type, $current_values) {
582
+
583
+ // Check if post type is supported
584
+ if(Permalink_Manager_Helper_Functions::is_disabled($post_type)) { return; }
585
+
586
+ // Get custom URI format
587
+ $custom_uri = (!empty($current_values['custom_uri'])) ? sanitize_text_field($current_values['custom_uri']) : "";
588
+
589
+ $html = '<div class="wpallimport-collapsed closed wpallimport-section">';
590
+ $html .= '<div class="wpallimport-content-section">';
591
+ $html .= sprintf('<div class="wpallimport-collapsed-header"><h3>%s</h3></div>', __('Permalink Manager', 'permalink-manager'));
592
+ $html .= '<div class="wpallimport-collapsed-content">';
593
+
594
+ $html .= '<div class="template_input">';
595
+ $html .= Permalink_Manager_Admin_Functions::generate_option_field('custom_uri', array('extra_atts' => 'style="width:100%; line-height: 25px;"', 'placeholder' => __('Custom URI', 'permalink-manager'), 'value' => $custom_uri));
596
+ $html .= wpautop(sprintf(__('If empty, a default permalink based on your current <a href="%s" target="_blank">permastructure settings</a> will be used.', 'permalink-manager'), Permalink_Manager_Admin_Functions::get_admin_url('&section=permastructs')));
597
+ $html .= '</div>';
598
+
599
+ // $html .= print_r($current_values, true);
600
+
601
+ $html .= '</div>';
602
+ $html .= '</div>';
603
+ $html .= '</div>';
604
+
605
+ echo $html;
606
+ }
607
+
608
+ function wpai_api_options($all_options) {
609
+ return $all_options + array('custom_uri' => null);
610
+ }
611
+
612
+ function wpai_api_register($addons) {
613
+ if(empty($addons[PERMALINK_MANAGER_PLUGIN_SLUG])) {
614
+ $addons[PERMALINK_MANAGER_PLUGIN_SLUG] = 1;
615
+ }
616
+ return $addons;
617
+ }
618
+
619
+ function wpai_api_parse($functions) {
620
+ $functions[PERMALINK_MANAGER_PLUGIN_SLUG] = array($this, 'wpai_api_parse_function');
621
+ return $functions;
622
+ }
623
+ function wpai_api_import($functions) {
624
+ $functions[PERMALINK_MANAGER_PLUGIN_SLUG] = array($this, 'wpai_api_import_function');
625
+ return $functions;
626
+ }
627
+
628
+ function wpai_api_parse_function($data) {
629
+ extract($data);
630
+
631
+ $data = array(); // parsed data
632
+ $option_name = 'custom_uri';
633
+
634
+ if(!empty($import->options[$option_name])) {
635
+ $this->logger = $data['logger'];
636
+ $cxpath = $xpath_prefix . $import->xpath;
637
+ $tmp_files = array();
638
+
639
+ if(isset($import->options[$option_name]) && $import->options[$option_name] != '') {
640
+ if($import->options[$option_name] == "xpath") {
641
+ if ($import->options[$this->slug]['xpaths'][$option_name] == "") {
642
+ $count and $this->data[$option_name] = array_fill(0, $count, "");
643
+ } else {
644
+ $data[$option_name] = XmlImportParser::factory($xml, $cxpath, (string) $import->options['xpaths'][$option_name], $file)->parse();
645
+ $tmp_files[] = $file;
646
+ }
647
+ } else {
648
+ $data[$option_name] = XmlImportParser::factory($xml, $cxpath, (string) $import->options[$option_name], $file)->parse();
649
+ $tmp_files[] = $file;
650
+ }
651
+ } else {
652
+ $data[$option_name] = array_fill(0, $count, "");
653
+ }
654
+
655
+ foreach ($tmp_files as $file) {
656
+ unlink($file);
657
+ }
658
+ }
659
+
660
+ return $data;
661
+ }
662
+
663
+ function wpai_api_import_function($importData, $parsedData) {
664
+ global $permalink_manager_uris;
665
+
666
+ // Get the parsed custom URI
667
+ $index = (!empty($importData['i'])) ? $importData['i'] : false;
668
+ $pid = (!empty($importData['pid'])) ? $importData['pid'] : false;
669
+
670
+ if($pid && $index && !empty($parsedData['custom_uri'][$index])) {
671
+ $custom_uri = $parsedData['custom_uri'][$index];
672
+
673
+ // Store only URIs
674
+ $custom_uri = parse_url($custom_uri, PHP_URL_PATH);
675
+
676
+ // Sanitize the output
677
+ $custom_uri = Permalink_Manager_Helper_Functions::sanitize_title($custom_uri);
678
+
679
+ $permalink_manager_uris[$pid] = $custom_uri;
680
+
681
+ update_option('permalink-manager-uris', $permalink_manager_uris);
682
+ }
683
+ }
684
+
685
+ function wpai_save_redirects($pid) {
686
+ global $permalink_manager_external_redirects;
687
+
688
+ $external_url = get_post_meta($pid, '_external_redirect', true);
689
+ $external_url = (empty($external_url)) ? get_post_meta($pid, 'external_redirect', true) : $external_url;
690
+
691
+ if($external_url && class_exists('Permalink_Manager_Pro_Functions')) {
692
+ Permalink_Manager_Pro_Functions::save_external_redirect($external_url, $pid);
693
+ }
694
+ }
695
+
696
  }
697
  ?>
includes/core/permalink-manager-uri-functions-post.php CHANGED
@@ -14,7 +14,10 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
14
  add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 99, 2);
15
  add_filter( 'attachment_link', array($this, 'custom_post_permalinks'), 99, 2);
16
 
17
- add_filter( 'permalink-manager-uris', array($this, 'exclude_homepage'), 99, 2);
 
 
 
18
 
19
  /**
20
  * URI Editor
@@ -135,7 +138,15 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
135
  // 1. Get the permastruct
136
  if($post_type == 'attachment') {
137
  $parent_page = ($post->post_parent > 0 && $post->post_parent != $post->ID) ? get_post($post->post_parent) : false;
138
- $default_permastruct = ($parent_page) ? trim(get_page_uri($parent_page->ID), "/") . "/attachment" : "";
 
 
 
 
 
 
 
 
139
 
140
  if($native_uri) {
141
  $permastruct = $default_permastruct;
@@ -273,9 +284,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
273
  }
274
 
275
  // 5. Clear the URI
276
- $default_uri = preg_replace('/\s+/', '', $default_uri);
277
- $default_uri = str_replace('//', '/', $default_uri);
278
- $default_uri = trim($default_uri, "/");
279
 
280
  return apply_filters('permalink_manager_filter_default_post_uri', $default_uri, $post->post_name, $post, $post_name, $native_uri);
281
  }
@@ -292,31 +301,34 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
292
  }
293
 
294
  /**
295
- * Find & replace (bulk action)
296
- */
297
- public static function find_and_replace() {
298
- global $wpdb, $permalink_manager_uris;
299
 
300
- // Check if post types & statuses are not empty
301
- if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
 
 
 
 
302
 
303
- // Get homepage URL and ensure that it ends with slash
304
- $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post) . "/";
305
 
306
- // Reset variables
307
- $updated_slugs_count = 0;
308
- $updated_array = array();
309
- $alert_type = $alert_content = $errors = '';
 
310
 
311
- // Process the variables from $_POST object
312
- $old_string = str_replace($home_url, '', esc_sql($_POST['old_string']));
313
- $new_string = str_replace($home_url, '', esc_sql($_POST['new_string']));
314
 
315
  $post_types_array = ($_POST['post_types']);
316
  $post_statuses_array = ($_POST['post_statuses']);
317
  $post_types = implode("', '", $post_types_array);
318
  $post_statuses = implode("', '", $post_statuses_array);
319
- $mode = isset($_POST['mode']) ? $_POST['mode'] : 'custom_uris';
320
 
321
  // Filter the posts by IDs
322
  $where = '';
@@ -343,12 +355,25 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
343
  }
344
 
345
  // Support for attachments
346
- if(in_array('attachment', $post_types_array)) {
347
- $attachment_support = " OR (post_type = 'attachment')";
348
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
349
 
350
  // Get the rows before they are altered
351
- $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}')){$attachment_support}) {$where}", ARRAY_A);
352
 
353
  // Now if the array is not empty use IDs from each subarray as a key
354
  if($posts_to_update && empty($errors)) {
@@ -361,7 +386,6 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
361
 
362
  // Do replacement on slugs (non-REGEX)
363
  if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
364
- // Use $_POST['old_string'] directly here & fix double slashes problem
365
  $regex = stripslashes(trim(sanitize_text_field($_POST['old_string']), "/"));
366
  $regex = preg_quote($regex, '~');
367
  $pattern = "~{$regex}~";
@@ -403,56 +427,16 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
403
  /**
404
  * Regenerate slugs & bases (bulk action)
405
  */
406
- static function regenerate_all_permalinks() {
407
  global $wpdb, $permalink_manager_uris;
408
 
409
- // Check if post types & statuses are not empty
410
- if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
411
-
412
- // Process the variables from $_POST object
413
  $updated_slugs_count = 0;
414
  $updated_array = array();
415
  $alert_type = $alert_content = $errors = '';
416
 
417
- $post_types_array = ($_POST['post_types']) ? ($_POST['post_types']) : '';
418
- $post_statuses_array = ($_POST['post_statuses']) ? $_POST['post_statuses'] : '';
419
- $post_types = implode("', '", $post_types_array);
420
- $post_statuses = implode("', '", $post_statuses_array);
421
- $mode = isset($_POST['mode']) ? $_POST['mode'] : 'custom_uris';
422
-
423
- // Filter the posts by IDs
424
- $where = '';
425
- if(!empty($_POST['ids'])) {
426
- // Remove whitespaces and prepare array with IDs and/or ranges
427
- $ids = esc_sql(preg_replace('/\s*/m', '', $_POST['ids']));
428
- preg_match_all("/([\d]+(?:-?[\d]+)?)/x", $ids, $groups);
429
-
430
- // Prepare the extra ID filters
431
- $where .= "AND (";
432
- foreach($groups[0] as $group) {
433
- $where .= ($group == reset($groups[0])) ? "" : " OR ";
434
- // A. Single number
435
- if(is_numeric($group)) {
436
- $where .= "(ID = {$group})";
437
- }
438
- // B. Range
439
- else if(substr_count($group, '-')) {
440
- $range_edges = explode("-", $group);
441
- $where .= "(ID BETWEEN {$range_edges[0]} AND {$range_edges[1]})";
442
- }
443
- }
444
- $where .= ")";
445
- }
446
-
447
- // Support for attachments
448
- if(in_array('attachment', $post_types_array)) {
449
- $attachment_support = " OR (post_type = 'attachment')";
450
- } else {
451
- $attachment_support = "";
452
- }
453
-
454
  // Get the rows before they are altered
455
- $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}')){$attachment_support}) {$where}", ARRAY_A);
456
 
457
  // Now if the array is not empty use IDs from each subarray as a key
458
  if($posts_to_update && empty($errors)) {
@@ -591,21 +575,22 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
591
 
592
  // Do not change anything if post is not saved yet (display sample permalink instead)
593
  if(get_option('page_on_front') == $id) {
594
- $uri = $sample_permalink_url = "";
595
  }
596
  else if($autosave || empty($post->post_status)) {
597
- $uri = $sample_permalink_url = $default_uri;
598
  } else {
599
- $uri = $sample_permalink_url = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri;
600
  }
601
 
602
  // Decode URI & allow to filter it
603
- $sample_permalink_url = apply_filters('permalink_manager_filter_post_sample_permalink', urldecode($sample_permalink_url), $post);
604
 
605
  // Prepare the sample & default permalink
606
- $sample_permalink = sprintf("{$home_url}/<span class=\"editable\">%s</span>", str_replace("//", "/", $sample_permalink_url));
607
 
608
  // Allow to filter the sample permalink URL
 
609
 
610
  // Append new HTML output
611
  $html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
@@ -614,6 +599,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
614
  // Append hidden field with native slug
615
  // $html .= (!empty($post->post_name)) ? "<input id=\"new-post-slug\" value=\"{$post->post_name}\" autocomplete=\"off\" type=\"hidden\">" : "";
616
  $html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$post->post_name}</span>" : "";
 
617
 
618
  return $html;
619
  }
@@ -753,9 +739,14 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
753
  }
754
 
755
  // Save only changed URIs
756
- if($new_uri != $old_uri) {
757
- $permalink_manager_uris[$post->ID] = $new_uri;
758
  update_option('permalink-manager-uris', $permalink_manager_uris);
 
 
 
 
 
759
  }
760
 
761
  do_action('permalink-manager-updated-post-uri', $post_id, $new_uri, $old_uri, $native_uri, $default_uri, $single_update = true);
14
  add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 99, 2);
15
  add_filter( 'attachment_link', array($this, 'custom_post_permalinks'), 99, 2);
16
 
17
+ add_filter( 'permalink-manager-uris', array($this, 'exclude_homepage'), 99);
18
+
19
+ // Support url_to_postid
20
+ add_filter( 'url_to_postid', array($this, 'url_to_postid'), 99);
21
 
22
  /**
23
  * URI Editor
138
  // 1. Get the permastruct
139
  if($post_type == 'attachment') {
140
  $parent_page = ($post->post_parent > 0 && $post->post_parent != $post->ID) ? get_post($post->post_parent) : false;
141
+ // $default_permastruct = ($parent_page) ? trim(get_page_uri($parent_page->ID), "/") . "/attachment" : "";
142
+
143
+ if(!empty($parent_page->ID)) {
144
+ $parent_page_uri = (!empty($permalink_manager_uris[$parent_page->ID])) ? $permalink_manager_uris[$parent_page->ID] : get_page_uri($parent_page->ID);
145
+ } else {
146
+ $parent_page_uri = "";
147
+ }
148
+
149
+ $default_permastruct = ($parent_page) ? trim($parent_page_uri, "/") . "/attachment" : "";
150
 
151
  if($native_uri) {
152
  $permastruct = $default_permastruct;
284
  }
285
 
286
  // 5. Clear the URI
287
+ $default_uri = Permalink_Manager_Helper_Functions::clear_single_uri($default_uri);
 
 
288
 
289
  return apply_filters('permalink_manager_filter_default_post_uri', $default_uri, $post->post_name, $post, $post_name, $native_uri);
290
  }
301
  }
302
 
303
  /**
304
+ * Support url_to_postid
305
+ */
306
+ public function url_to_postid($url) {
307
+ $post = Permalink_Manager_Core_Functions::detect_post(null, $url, true);
308
 
309
+ if(!empty($post->ID)) {
310
+ $native_uri = self::get_default_post_uri($post->ID, true);
311
+ $native_url = sprintf("%s/%s", trim(home_url(), "/"), $native_uri);
312
+ } else {
313
+ $native_uri = '';
314
+ }
315
 
316
+ return (!empty($native_uri)) ? $native_uri : $url;
317
+ }
318
 
319
+ /**
320
+ * Bulk tools
321
+ */
322
+ public static function get_items() {
323
+ global $wpdb;
324
 
325
+ // Check if post types & statuses are not empty
326
+ if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
 
327
 
328
  $post_types_array = ($_POST['post_types']);
329
  $post_statuses_array = ($_POST['post_statuses']);
330
  $post_types = implode("', '", $post_types_array);
331
  $post_statuses = implode("', '", $post_statuses_array);
 
332
 
333
  // Filter the posts by IDs
334
  $where = '';
355
  }
356
 
357
  // Support for attachments
358
+ $attachment_support = (in_array('attachment', $post_types_array)) ? " OR (post_type = 'attachment')" : "";
359
+
360
+ // Get the rows before they are altered
361
+ return $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE ((post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')){$attachment_support}) {$where}", ARRAY_A);
362
+ }
363
+
364
+ /**
365
+ * Find & replace (bulk action)
366
+ */
367
+ public static function find_and_replace($chunk = null, $mode = '', $old_string = '', $new_string = '') {
368
+ global $wpdb, $permalink_manager_uris;
369
+
370
+ // Reset variables
371
+ $updated_slugs_count = 0;
372
+ $updated_array = array();
373
+ $alert_type = $alert_content = $errors = '';
374
 
375
  // Get the rows before they are altered
376
+ $posts_to_update = ($chunk) ? $chunk : self::get_items();
377
 
378
  // Now if the array is not empty use IDs from each subarray as a key
379
  if($posts_to_update && empty($errors)) {
386
 
387
  // Do replacement on slugs (non-REGEX)
388
  if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
 
389
  $regex = stripslashes(trim(sanitize_text_field($_POST['old_string']), "/"));
390
  $regex = preg_quote($regex, '~');
391
  $pattern = "~{$regex}~";
427
  /**
428
  * Regenerate slugs & bases (bulk action)
429
  */
430
+ static function regenerate_all_permalinks($chunk = null, $mode = '') {
431
  global $wpdb, $permalink_manager_uris;
432
 
433
+ // Reset variables
 
 
 
434
  $updated_slugs_count = 0;
435
  $updated_array = array();
436
  $alert_type = $alert_content = $errors = '';
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  // Get the rows before they are altered
439
+ $posts_to_update = ($chunk) ? $chunk : self::get_items();
440
 
441
  // Now if the array is not empty use IDs from each subarray as a key
442
  if($posts_to_update && empty($errors)) {
575
 
576
  // Do not change anything if post is not saved yet (display sample permalink instead)
577
  if(get_option('page_on_front') == $id) {
578
+ $uri = $sample_permalink_uri = "";
579
  }
580
  else if($autosave || empty($post->post_status)) {
581
+ $uri = $sample_permalink_uri = $default_uri;
582
  } else {
583
+ $uri = $sample_permalink_uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri;
584
  }
585
 
586
  // Decode URI & allow to filter it
587
+ $sample_permalink_uri = apply_filters('permalink_manager_filter_post_sample_uri', urldecode($sample_permalink_uri), $post);
588
 
589
  // Prepare the sample & default permalink
590
+ $sample_permalink = sprintf("{$home_url}/<span class=\"editable\">%s</span>", str_replace("//", "/", $sample_permalink_uri));
591
 
592
  // Allow to filter the sample permalink URL
593
+ $sample_permalink = apply_filters('permalink_manager_filter_post_sample_permalink', $sample_permalink, $post);
594
 
595
  // Append new HTML output
596
  $html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
599
  // Append hidden field with native slug
600
  // $html .= (!empty($post->post_name)) ? "<input id=\"new-post-slug\" value=\"{$post->post_name}\" autocomplete=\"off\" type=\"hidden\">" : "";
601
  $html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$post->post_name}</span>" : "";
602
+ // $html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$uri}</span>" : "";
603
 
604
  return $html;
605
  }
739
  }
740
 
741
  // Save only changed URIs
742
+ //if($new_uri != $old_uri) {
743
+ $permalink_manager_uris[$post_id] = $new_uri;
744
  update_option('permalink-manager-uris', $permalink_manager_uris);
745
+ //}
746
+
747
+ // Update the slug (if changed)
748
+ if(!empty($_POST['post_name']) && isset($_POST['native_slug']) && ($_POST['native_slug'] !== $_POST['post_name'])) {
749
+ self::update_slug_by_id($_POST['native_slug'], $post_id);
750
  }
751
 
752
  do_action('permalink-manager-updated-post-uri', $post_id, $new_uri, $old_uri, $native_uri, $default_uri, $single_update = true);
includes/views/permalink-manager-settings.php CHANGED
@@ -39,6 +39,12 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
39
  'label' => __('Auto-update permalinks', 'permalink-manager'),
40
  'input_class' => '',
41
  'description' => __('If enabled, the custom permalinks will be automatically updated every time the post is saved or updated.', 'permalink-manager')
 
 
 
 
 
 
42
  )
43
  )
44
  ),
39
  'label' => __('Auto-update permalinks', 'permalink-manager'),
40
  'input_class' => '',
41
  'description' => __('If enabled, the custom permalinks will be automatically updated every time the post is saved or updated.', 'permalink-manager')
42
+ ),
43
+ 'show_native_slug_field' => array(
44
+ 'type' => 'single_checkbox',
45
+ 'label' => __('Show "Native slug" field', 'permalink-manager'),
46
+ 'input_class' => '',
47
+ 'description' => __('If enabled, it would be possible to edit the native slug via URI Editor on single post/term edit page.', 'permalink-manager')
48
  )
49
  )
50
  ),
includes/views/permalink-manager-tools.php CHANGED
@@ -52,7 +52,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
52
  $home_url = trim(get_option('home'), "/");
53
 
54
  $html = sprintf("<h3>%s</h3>", __("List of duplicated permalinks", "permalink-manager"));
55
- $html .= wpautop(sprintf("<a class=\"button button-primary\" href=\"%s\">%s</a>", admin_url('tools.php?page=permalink-manager&section=tools&subsection=duplicates&clear-permalink-manager-uris=1'), __('Remove all broken URIs', 'permalink-manager')));
56
 
57
  if(!empty($all_duplicates)) {
58
  foreach($all_duplicates as $uri => $duplicates) {
@@ -103,7 +103,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
103
  }
104
 
105
  $html .= sprintf(
106
- '<td><a href="%1$s">%2$s</a>%3$s</td><td>%4$s</td><td class="actions"><a href="%1$s" target="_blank">%5$s</a>%6$s</td>',
107
  $edit_link,
108
  $title,
109
  " <small>#{$detected_id}</small>",
52
  $home_url = trim(get_option('home'), "/");
53
 
54
  $html = sprintf("<h3>%s</h3>", __("List of duplicated permalinks", "permalink-manager"));
55
+ $html .= wpautop(sprintf("<a class=\"button button-primary\" href=\"%s\">%s</a>", admin_url('tools.php?page=permalink-manager&section=tools&subsection=duplicates&clear-permalink-manager-uris=1'), __('Fix custom permalinks & redirects', 'permalink-manager')));
56
 
57
  if(!empty($all_duplicates)) {
58
  foreach($all_duplicates as $uri => $duplicates) {
103
  }
104
 
105
  $html .= sprintf(
106
+ '<td><a href="%1$s">%2$s</a>%3$s</td><td>%4$s</td><td class="actions"><a href="%1$s">%5$s</a>%6$s</td>',
107
  $edit_link,
108
  $title,
109
  " <small>#{$detected_id}</small>",
includes/views/permalink-manager-uri-editor-post.php CHANGED
@@ -27,6 +27,7 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
27
 
28
  $output = "<form id=\"permalinks-post-types-table\" class=\"slugs-table\" method=\"post\">";
29
  $output .= wp_nonce_field('permalink-manager', 'uri_editor', true, true);
 
30
 
31
  // Bypass
32
  ob_start();
@@ -144,11 +145,17 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
144
  $html .= get_submit_button( ${"button_$which"}, 'primary alignleft', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
145
 
146
  if ($which == "top") {
 
 
 
 
 
 
147
  $months = $wpdb->get_results("SELECT DISTINCT month(post_date) AS m, year(post_date) AS y FROM {$wpdb->posts} WHERE post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types) ORDER BY post_date DESC", ARRAY_A);
148
  if($months) {
149
  $month_key = 'month';
150
  $screen = get_current_screen();
151
- $current_url = add_query_arg( array(
152
  'page' => PERMALINK_MANAGER_PLUGIN_SLUG,
153
  'section' => $active_section,
154
  'subsection' => $active_subsection
@@ -174,6 +181,21 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
174
  echo $html;
175
  }
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  /**
178
  * Prepare the items for the table to process
179
  */
@@ -192,6 +214,7 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
192
  $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
193
  $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
194
  $offset = ($current_page - 1) * $per_page;
 
195
 
196
  // Extra filters
197
  $extra_filters = $attachment_support = '';
@@ -209,7 +232,17 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
209
 
210
  // Grab posts from database
211
  $sql_parts['start'] = "SELECT * FROM {$wpdb->posts} ";
212
- $sql_parts['where'] = "WHERE ((post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types)) {$attachment_support}) {$extra_filters} ";
 
 
 
 
 
 
 
 
 
 
213
  $sql_parts['end'] = "ORDER BY {$orderby} {$order}";
214
 
215
  $sql_query = implode("", $sql_parts);
27
 
28
  $output = "<form id=\"permalinks-post-types-table\" class=\"slugs-table\" method=\"post\">";
29
  $output .= wp_nonce_field('permalink-manager', 'uri_editor', true, true);
30
+ $output .= Permalink_Manager_Admin_Functions::generate_option_field('pm_session_id', array('value' => uniqid(), 'type' => 'hidden'));
31
 
32
  // Bypass
33
  ob_start();
145
  $html .= get_submit_button( ${"button_$which"}, 'primary alignleft', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
146
 
147
  if ($which == "top") {
148
+ // Searchbox
149
+ $html .= '<div class="alignright">';
150
+ $html .= $this->search_box(__('Search', 'permalink-manager'), 'search-input');
151
+ $html .= '</div>';
152
+
153
+ // Filter by date
154
  $months = $wpdb->get_results("SELECT DISTINCT month(post_date) AS m, year(post_date) AS y FROM {$wpdb->posts} WHERE post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types) ORDER BY post_date DESC", ARRAY_A);
155
  if($months) {
156
  $month_key = 'month';
157
  $screen = get_current_screen();
158
+ $current_url = add_query_arg(array(
159
  'page' => PERMALINK_MANAGER_PLUGIN_SLUG,
160
  'section' => $active_section,
161
  'subsection' => $active_subsection
181
  echo $html;
182
  }
183
 
184
+ /**
185
+ * Search box
186
+ */
187
+ public function search_box($text = '', $input_id = '') {
188
+ $search_query = (!empty($_REQUEST['s'])) ? esc_attr(wp_unslash($_REQUEST['s'])) : "";
189
+
190
+ $output = "<p class=\"search-box\">";
191
+ $output .= "<label class=\"screen-reader-text\" for=\"{$input_id}\">{$text}:</label>";
192
+ $output .= Permalink_Manager_Admin_Functions::generate_option_field('s', array('value' => $search_query, 'type' => 'search'));
193
+ $output .= get_submit_button($text, 'button', false, false, array('id' => 'search-submit', 'name' => 'search-submit'));
194
+ $output .= "</p>";
195
+
196
+ return $output;
197
+ }
198
+
199
  /**
200
  * Prepare the items for the table to process
201
  */
214
  $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
215
  $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
216
  $offset = ($current_page - 1) * $per_page;
217
+ $search_query = (!empty($_REQUEST['s'])) ? esc_sql($_REQUEST['s']) : "";
218
 
219
  // Extra filters
220
  $extra_filters = $attachment_support = '';
232
 
233
  // Grab posts from database
234
  $sql_parts['start'] = "SELECT * FROM {$wpdb->posts} ";
235
+ if($search_query) {
236
+ $sql_parts['where'] = "WHERE post_name LIKE ('%{$search_query}%') ";
237
+
238
+ // Search in array with custom URIs
239
+ $found = Permalink_Manager_Helper_Functions::search_uri($search_query, 'posts');
240
+ if($found) {
241
+ $sql_parts['where'] .= sprintf("OR ID IN ('%s')", implode(',', (array) $found));
242
+ }
243
+ } else {
244
+ $sql_parts['where'] = "WHERE ((post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types)) {$attachment_support}) {$extra_filters} ";
245
+ }
246
  $sql_parts['end'] = "ORDER BY {$orderby} {$order}";
247
 
248
  $sql_query = implode("", $sql_parts);
out/permalink-manager-admin.css CHANGED
@@ -6,6 +6,7 @@
6
  #permalink-manager h4{font-size:18px;margin-bottom:10px}
7
  #permalink-manager h5{font-size:15px;margin-bottom:10px}
8
  #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
 
9
  #permalink-manager .settings-select{min-width:200px}
10
  #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
11
  #permalink-manager .margin-top{margin-top:15px}
@@ -27,6 +28,7 @@
27
  #permalink-manager .tablenav.top{margin-top:0}
28
  #permalink-manager .tablenav .actions{padding:0;overflow:visible}
29
  #permalink-manager .tablenav #months-filter{margin-left:10px}
 
30
  #permalink-manager th#count a{display:inline-block}
31
  #permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
32
  #permalink-manager .post_permalink{margin-top:5px;display:block}
@@ -64,6 +66,7 @@
64
  #permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both}
65
  #permalink-manager .field-description{font-size:12px}
66
  #permalink-manager .appended-row td{padding-left:0;padding-right:0}
 
67
  #permalink-manager #tools select{min-width:60%}
68
  #permalink-manager fieldset label{margin-bottom:0 !important}
69
 
6
  #permalink-manager h4{font-size:18px;margin-bottom:10px}
7
  #permalink-manager h5{font-size:15px;margin-bottom:10px}
8
  #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
9
+ #permalink-manager .mute{color:#888}
10
  #permalink-manager .settings-select{min-width:200px}
11
  #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
12
  #permalink-manager .margin-top{margin-top:15px}
28
  #permalink-manager .tablenav.top{margin-top:0}
29
  #permalink-manager .tablenav .actions{padding:0;overflow:visible}
30
  #permalink-manager .tablenav #months-filter{margin-left:10px}
31
+ #permalink-manager .search-box{margin-left:1em}
32
  #permalink-manager th#count a{display:inline-block}
33
  #permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
34
  #permalink-manager .post_permalink{margin-top:5px;display:block}
66
  #permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both}
67
  #permalink-manager .field-description{font-size:12px}
68
  #permalink-manager .appended-row td{padding-left:0;padding-right:0}
69
+ #permalink-manager #tools{margin:0 -15px;padding:0 15px 15px}
70
  #permalink-manager #tools select{min-width:60%}
71
  #permalink-manager fieldset label{margin-bottom:0 !important}
72
 
out/permalink-manager-admin.js CHANGED
@@ -202,7 +202,7 @@ jQuery(document).ready(function() {
202
  * Restore "Default URI"
203
  */
204
  jQuery('#permalink-manager .restore-default').on('click', function() {
205
- var input = jQuery(this).parents('.field-container, .permalink-manager-edit-uri-box').find('input[data-default]');
206
  jQuery(input).val(jQuery(input).data('default')).trigger('keyup');
207
  return false;
208
  });
@@ -222,6 +222,132 @@ jQuery(document).ready(function() {
222
  });
223
  });
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  /**
226
  * Help tooltips
227
  */
202
  * Restore "Default URI"
203
  */
204
  jQuery('#permalink-manager .restore-default').on('click', function() {
205
+ var input = jQuery(this).parents('.field-container, .permalink-manager-edit-uri-box').find('input.custom_uri');
206
  jQuery(input).val(jQuery(input).data('default')).trigger('keyup');
207
  return false;
208
  });
222
  });
223
  });
224
 
225
+ /**
226
+ * Check expiration date
227
+ */
228
+ jQuery(document).on('click', '#pm_get_exp_date', function() {
229
+ jQuery.ajax(permalink_manager.ajax_url, {
230
+ type: 'POST',
231
+ data: {
232
+ action: 'pm_get_exp_date',
233
+ },
234
+ beforeSend: function() {
235
+ var spinner = '<img src="' + permalink_manager.spinners + '/wpspin_light-2x.gif" width="16" height="16">';
236
+ jQuery('#permalink-manager .licence-info').html(spinner);
237
+ },
238
+ success: function(data) {
239
+ jQuery('#permalink-manager .licence-info').html(data);
240
+ }
241
+ });
242
+
243
+ return false;
244
+ });
245
+
246
+ /**
247
+ * Bulk tools
248
+ */
249
+ function pm_show_progress(elem, progress) {
250
+ if(progress) {
251
+ jQuery(elem).LoadingOverlay("text", progress + "%");
252
+ } else {
253
+ jQuery(elem).LoadingOverlay("show", {
254
+ background : "rgba(0, 0, 0, 0.1)",
255
+ text: '0%'
256
+ });
257
+ }
258
+ }
259
+
260
+ jQuery('#permalink-manager #tools form').on('submit', function() {
261
+ var data = jQuery(this).serialize() + '&action=' + 'pm_bulk_tools';
262
+ var form = jQuery(this);
263
+ var updated_count = total = progress = 0;
264
+
265
+ // Hide alert & results table
266
+ jQuery('#permalink-manager .updated-slugs-table, .permalink-manager-notice.updated_slugs, #permalink-manager #updated-list').remove();
267
+
268
+ jQuery.ajax({
269
+ type: 'POST',
270
+ url: permalink_manager.ajax_url,
271
+ data: data,
272
+ beforeSend: function() {
273
+ // Show progress overlay
274
+ pm_show_progress("#permalink-manager #tools", progress);
275
+ },
276
+ success: function(data) {
277
+ var table_dom = jQuery('#permalink-manager .updated-slugs-table');
278
+ // console.log(data);
279
+
280
+ // Display the table
281
+ if(data.hasOwnProperty('html')) {
282
+ var table = jQuery(data.html);
283
+
284
+ if(table_dom.length == 0) {
285
+ jQuery('#permalink-manager #tools').after(data.html);
286
+ } else {
287
+ jQuery(table_dom).append(jQuery(table).find('tbody').html());
288
+ }
289
+ }
290
+
291
+ // Hide error message
292
+ jQuery('.permalink-manager-notice.updated_slugs.error').remove();
293
+
294
+ // Display the alert (should be hidden at first)
295
+ if(data.hasOwnProperty('alert') && jQuery('.permalink-manager-notice.updated_slugs .updated_count').length == 0) {
296
+ var alert = jQuery(data.alert).hide();
297
+ jQuery('#plugin-name-heading').after(alert);
298
+ }
299
+
300
+ // Increase updated count
301
+ if(data.hasOwnProperty('updated_count')) {
302
+ if(jQuery(form).attr("data-updated_count")) {
303
+ updated_count = parseInt(jQuery(form).attr("data-updated_count")) + parseInt(data.updated_count);
304
+ } else {
305
+ updated_count = parseInt(data.updated_count);
306
+ }
307
+
308
+ jQuery(form).attr("data-updated_count", updated_count);
309
+ jQuery('.permalink-manager-notice.updated_slugs .updated_count').text(updated_count);
310
+ }
311
+
312
+ // Show total
313
+ if(data.hasOwnProperty('total')) {
314
+ total = parseInt(data.total);
315
+
316
+ jQuery(form).attr("data-total", total);
317
+ }
318
+
319
+ // Trigger again
320
+ if(data.hasOwnProperty('left_chunks')) {
321
+ jQuery.ajax(this);
322
+
323
+ // Update progress
324
+ if(data.hasOwnProperty('progress')) {
325
+ console.log(data.progress);
326
+ console.log(total);
327
+
328
+ progress = Math.floor((data.progress / total) * 100)
329
+ }
330
+ } else {
331
+ // Display results
332
+ jQuery('.permalink-manager-notice.updated_slugs').fadeIn();
333
+ jQuery('#permalink-manager #tools').LoadingOverlay("hide", true);
334
+
335
+ if(table_dom.length > 0) {
336
+ jQuery('html, body').animate({
337
+ scrollTop: table_dom.offset().top - 100
338
+ }, 2000);
339
+ }
340
+
341
+ // Reset progress & updated count
342
+ progress = updated_count = 0;
343
+ jQuery(form).attr("data-updated_count", 0);
344
+ }
345
+ }
346
+ });
347
+
348
+ return false;
349
+ });
350
+
351
  /**
352
  * Help tooltips
353
  */
out/permalink-manager-plugins.js CHANGED
@@ -16,3 +16,12 @@
16
  * @version 2.1.3
17
  */
18
  !function(e,t,n){function y(e){return t.createElement(e)}function x(e){return Object.keys(e)}function C(e){return x(e).length}var i="__instance__",r=setTimeout,s="innerHTML",a="textContent",o="className",f="classes",u="toLowerCase",l="replace",c="firstChild",p="parentNode",g="nextSibling",d="previousSibling",v="appendChild",h="insertBefore",b="removeChild",m="setAttribute",w="getAttribute",j="preventDefault",k="addEventListener";!function(e){e.version="2.1.3",e[i]={},e.each=function(t,n){return r(function(){var r,n=e[i];for(r in n)t(n[r],r,n)},0===n?0:n||1),e}}(e[n]=function(t,D){function H(){B.focus()}function I(e){var n,t=e?this:B;r(function(){n=t[a].split(N.join);for(K in n)_.set(n[K])},1)}var B,K,O,_=this,E=Date.now(),L=t.placeholder||"",N={join:", ",max:9999,escape:[",","\n"],alert:!0,text:["Delete “%s”","Duplicate “%s”"],classes:["tags","tag","tags-input","tags-output","tags-view"],update:function(){}},S=y("span"),T=y("span"),A="data-tag";e[n][i][t.id||t.name||C(e[n][i])]=_,D="string"==typeof D?{join:D}:D||{};for(K in N)"undefined"!=typeof D[K]&&(N[K]=D[K]);t[o]=N[f][3],S[o]=N[f][0]+" "+N[f][0]+"-"+E,S[k]("click",H,!1),S.id=N[f][0]+":"+(t.id||E),S[s]='<span class="'+N[f][4]+'"></span>',T[o]=N[f][2],T[s]='<span contenteditable spellcheck="false" style="white-space:nowrap;outline:none;"></span><span>'+L+"</span>",t[p][h](S,t[g]||null),S[c][v](T),B=T[c],_.tags={},_.error=0,_.filter=function(e){return(e+"")[l](new RegExp("["+N.join[l](/\s/g,"")+"]|\\s{2,}|^\\s+|\\s+$","g"),"")[u]()},_.update=function(e,n){for(t.value="";(K=S[c][c])&&K[w](A);)S[c][b](K);if(0===e)e=x(_.tags);else{for(K in e)O=_.filter(e[K]),O&&(_.tags[O]=1);e=x(_.tags)}_.tags={};for(K in e)_.set(e[K],n);return N.update(_),_},_.reset=function(e){return e=_.filter(e||""),e?delete _.tags[e]:_.tags={},_.update(0,1)},_.set=function(e,n){if(e=_.filter(e),""===e||C(_.tags)===N.max)return B[s]="",_;var i=y("span"),r=y("a");if(i[o]=N[f][1],i[m](A,e),r.href="javascript:;",r.title=(N.text[0]||"")[l](/%s/g,e),r[k]("click",function(e){var t=this,n=t[p],i=t[p][w](A);n[p][b](n),_.reset(i),H(),e[j]()},!1),i[v](r),B[s]="",B[g][s]=L,_.tags[e]){if(n)S[c][h](i,T);else if(N.alert){_.error=1;var a=(N.text[1]||e)[l](/%s/g,e);"function"==typeof N.alert?N.alert(a,e,_):alert(a)}}else _.tags[e]=1,S[c][h](i,T);return t.value=x(_.tags).join(N.join),!n&&N.update(_),_},function(){return B[k]("blur",function(){_.error=0,_.set(this[a])},!1),B[k]("paste",I,!1),B[k]("keydown",function(e){_.error=0;var y,t=this,n=e.keyCode,i=S,o=(e.key||String.fromCharCode(n))[u](),f=e.ctrlKey,l=e.shiftKey,c=T[d]&&T[d][w](A),v=B[g],h="tab"===o||!l&&9===n,b="enter"===o||!l&&13===n,m=" "===o||!l&&32===n,k="backspace"===o||!l&&8===n;if(!f&&b){for(;i=i[p];)if("form"===i.nodeName[u]()){y=i;break}_.set(t[a]),0===_.error&&y&&y.submit()}else if(f&&("v"===o||!l&&86===n))I();else if(!t[a]&&k)_.reset(c),H();else{var C,D,x=N.escape;for(K in x)if(C=x[K],D="s"===C,(D||" "===C)&&h||(D||"\n"===C)&&b||(D||" "===C)&&m)return r(function(){_.set(t[a]),H()},1),void e[j]();r(function(){var e=t[a];for(v[s]=e?"":L,K=0,O=x.length;O>K;++K)if(x[K]&&-1!==e.indexOf(x[K])){_.set(e.split(x[K]).join(""));break}},1)}},!1),_}(),_.update(t.value.split(N.join),1),_.config=N,_.input=T,_.view=S,_.target=_.output=t})}(window,document,"TIB");
 
 
 
 
 
 
 
 
 
16
  * @version 2.1.3
17
  */
18
  !function(e,t,n){function y(e){return t.createElement(e)}function x(e){return Object.keys(e)}function C(e){return x(e).length}var i="__instance__",r=setTimeout,s="innerHTML",a="textContent",o="className",f="classes",u="toLowerCase",l="replace",c="firstChild",p="parentNode",g="nextSibling",d="previousSibling",v="appendChild",h="insertBefore",b="removeChild",m="setAttribute",w="getAttribute",j="preventDefault",k="addEventListener";!function(e){e.version="2.1.3",e[i]={},e.each=function(t,n){return r(function(){var r,n=e[i];for(r in n)t(n[r],r,n)},0===n?0:n||1),e}}(e[n]=function(t,D){function H(){B.focus()}function I(e){var n,t=e?this:B;r(function(){n=t[a].split(N.join);for(K in n)_.set(n[K])},1)}var B,K,O,_=this,E=Date.now(),L=t.placeholder||"",N={join:", ",max:9999,escape:[",","\n"],alert:!0,text:["Delete “%s”","Duplicate “%s”"],classes:["tags","tag","tags-input","tags-output","tags-view"],update:function(){}},S=y("span"),T=y("span"),A="data-tag";e[n][i][t.id||t.name||C(e[n][i])]=_,D="string"==typeof D?{join:D}:D||{};for(K in N)"undefined"!=typeof D[K]&&(N[K]=D[K]);t[o]=N[f][3],S[o]=N[f][0]+" "+N[f][0]+"-"+E,S[k]("click",H,!1),S.id=N[f][0]+":"+(t.id||E),S[s]='<span class="'+N[f][4]+'"></span>',T[o]=N[f][2],T[s]='<span contenteditable spellcheck="false" style="white-space:nowrap;outline:none;"></span><span>'+L+"</span>",t[p][h](S,t[g]||null),S[c][v](T),B=T[c],_.tags={},_.error=0,_.filter=function(e){return(e+"")[l](new RegExp("["+N.join[l](/\s/g,"")+"]|\\s{2,}|^\\s+|\\s+$","g"),"")[u]()},_.update=function(e,n){for(t.value="";(K=S[c][c])&&K[w](A);)S[c][b](K);if(0===e)e=x(_.tags);else{for(K in e)O=_.filter(e[K]),O&&(_.tags[O]=1);e=x(_.tags)}_.tags={};for(K in e)_.set(e[K],n);return N.update(_),_},_.reset=function(e){return e=_.filter(e||""),e?delete _.tags[e]:_.tags={},_.update(0,1)},_.set=function(e,n){if(e=_.filter(e),""===e||C(_.tags)===N.max)return B[s]="",_;var i=y("span"),r=y("a");if(i[o]=N[f][1],i[m](A,e),r.href="javascript:;",r.title=(N.text[0]||"")[l](/%s/g,e),r[k]("click",function(e){var t=this,n=t[p],i=t[p][w](A);n[p][b](n),_.reset(i),H(),e[j]()},!1),i[v](r),B[s]="",B[g][s]=L,_.tags[e]){if(n)S[c][h](i,T);else if(N.alert){_.error=1;var a=(N.text[1]||e)[l](/%s/g,e);"function"==typeof N.alert?N.alert(a,e,_):alert(a)}}else _.tags[e]=1,S[c][h](i,T);return t.value=x(_.tags).join(N.join),!n&&N.update(_),_},function(){return B[k]("blur",function(){_.error=0,_.set(this[a])},!1),B[k]("paste",I,!1),B[k]("keydown",function(e){_.error=0;var y,t=this,n=e.keyCode,i=S,o=(e.key||String.fromCharCode(n))[u](),f=e.ctrlKey,l=e.shiftKey,c=T[d]&&T[d][w](A),v=B[g],h="tab"===o||!l&&9===n,b="enter"===o||!l&&13===n,m=" "===o||!l&&32===n,k="backspace"===o||!l&&8===n;if(!f&&b){for(;i=i[p];)if("form"===i.nodeName[u]()){y=i;break}_.set(t[a]),0===_.error&&y&&y.submit()}else if(f&&("v"===o||!l&&86===n))I();else if(!t[a]&&k)_.reset(c),H();else{var C,D,x=N.escape;for(K in x)if(C=x[K],D="s"===C,(D||" "===C)&&h||(D||"\n"===C)&&b||(D||" "===C)&&m)return r(function(){_.set(t[a]),H()},1),void e[j]();r(function(){var e=t[a];for(v[s]=e?"":L,K=0,O=x.length;O>K;++K)if(x[K]&&-1!==e.indexOf(x[K])){_.set(e.split(x[K]).join(""));break}},1)}},!1),_}(),_.update(t.value.split(N.join),1),_.config=N,_.input=T,_.view=S,_.target=_.output=t})}(window,document,"TIB");
19
+
20
+ /**
21
+ * LoadingOverlay
22
+ * Copyright (c) Gaspare Sganga
23
+ * https://gasparesganga.com/labs/jquery-loading-overlay/
24
+ * @license MIT
25
+ * @version 2.1.5
26
+ */
27
+ !function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?e(require("jquery")):e(jQuery)}(function(e,s){"use strict";var t={background:"rgba(255, 255, 255, 0.8)",backgroundClass:"",image:"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'><circle r='80' cx='500' cy='90'/><circle r='80' cx='500' cy='910'/><circle r='80' cx='90' cy='500'/><circle r='80' cx='910' cy='500'/><circle r='80' cx='212' cy='212'/><circle r='80' cx='788' cy='212'/><circle r='80' cx='212' cy='788'/><circle r='80' cx='788' cy='788'/></svg>",imageAnimation:"2000ms rotate_right",imageAutoResize:!0,imageResizeFactor:1,imageColor:"#202020",imageClass:"",imageOrder:1,fontawesome:"",fontawesomeAnimation:"",fontawesomeAutoResize:!0,fontawesomeResizeFactor:1,fontawesomeColor:"#202020",fontawesomeOrder:2,custom:"",customAnimation:"",customAutoResize:!0,customResizeFactor:1,customOrder:3,text:"",textAnimation:"",textAutoResize:!0,textResizeFactor:.5,textColor:"#202020",textClass:"",textOrder:4,progress:!1,progressAutoResize:!0,progressResizeFactor:.25,progressColor:"#a0a0a0",progressClass:"",progressOrder:5,progressFixedPosition:"",progressSpeed:200,progressMin:0,progressMax:100,size:50,maxSize:120,minSize:20,direction:"column",fade:!0,resizeInterval:50,zIndex:2147483647},a={overlay:{"box-sizing":"border-box",position:"relative",display:"flex","flex-wrap":"nowrap","align-items":"center","justify-content":"space-around"},element:{"box-sizing":"border-box",overflow:"visible",flex:"0 0 auto",display:"flex","justify-content":"center","align-items":"center"},element_svg:{width:"100%",height:"100%"},progress_fixed:{position:"absolute",left:"0",width:"100%"},progress_wrapper:{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"},progress_bar:{position:"absolute",left:"0"}},o={count:0,container:s,settings:s,wholePage:s,resizeIntervalId:s,text:s,progress:s},r={animations:["rotate_right","rotate_left","fadein","pulse"],progressPosition:["top","bottom"]},i={animations:{name:"rotate_right",time:"2000ms"},fade:[400,200]};function n(s,t){s=e(s),t.size=y(t.size),t.maxSize=parseInt(t.maxSize,10)||0,t.minSize=parseInt(t.minSize,10)||0,t.resizeInterval=parseInt(t.resizeInterval,10)||0;var r=f(s),n=p(s);if(!1===n){if((n=e.extend({},o)).container=s,n.wholePage=s.is("body"),r=e("<div>",{class:"loadingoverlay"}).css(a.overlay).css("flex-direction","row"===t.direction.toLowerCase()?"row":"column"),t.backgroundClass?r.addClass(t.backgroundClass):r.css("background",t.background),n.wholePage&&r.css({position:"fixed",top:0,left:0,width:"100%",height:"100%"}),void 0!==t.zIndex&&r.css("z-index",t.zIndex),t.image){e.isArray(t.imageColor)?0===t.imageColor.length?t.imageColor=!1:1===t.imageColor.length?t.imageColor={fill:t.imageColor[0]}:t.imageColor={fill:t.imageColor[0],stroke:t.imageColor[1]}:t.imageColor&&(t.imageColor={fill:t.imageColor});var l=u(r,t.imageOrder,t.imageAutoResize,t.imageResizeFactor,t.imageAnimation);"<svg"===t.image.slice(0,4).toLowerCase()&&"</svg>"===t.image.slice(-6).toLowerCase()?(l.append(t.image),l.children().css(a.element_svg),!t.imageClass&&t.imageColor&&l.find("*").css(t.imageColor)):".svg"===t.image.slice(-4).toLowerCase()||"data:image/svg"===t.image.slice(0,14).toLowerCase()?e.ajax({url:t.image,type:"GET",dataType:"html",global:!1}).done(function(e){l.html(e),l.children().css(a.element_svg),!t.imageClass&&t.imageColor&&l.find("*").css(t.imageColor)}):l.css({"background-image":"url("+t.image+")","background-position":"center","background-repeat":"no-repeat","background-size":"cover"}),t.imageClass&&l.addClass(t.imageClass)}if(t.fontawesome){l=u(r,t.fontawesomeOrder,t.fontawesomeAutoResize,t.fontawesomeResizeFactor,t.fontawesomeAnimation).addClass("loadingoverlay_fa");e("<div>",{class:t.fontawesome}).appendTo(l),t.fontawesomeColor&&l.css("color",t.fontawesomeColor)}if(t.custom)l=u(r,t.customOrder,t.customAutoResize,t.customResizeFactor,t.customAnimation).append(t.custom);if(t.text&&(n.text=u(r,t.textOrder,t.textAutoResize,t.textResizeFactor,t.textAnimation).addClass("loadingoverlay_text").text(t.text),t.textClass?n.text.addClass(t.textClass):t.textColor&&n.text.css("color",t.textColor)),t.progress){l=u(r,t.progressOrder,t.progressAutoResize,t.progressResizeFactor,!1).addClass("loadingoverlay_progress");var g=e("<div>").css(a.progress_wrapper).appendTo(l);n.progress={bar:e("<div>").css(a.progress_bar).appendTo(g),fixed:!1,margin:0,min:parseFloat(t.progressMin),max:parseFloat(t.progressMax),speed:parseInt(t.progressSpeed,10)};var c=(t.progressFixedPosition+"").replace(/\s\s+/g," ").toLowerCase().split(" ");2===c.length&&h(c[0])?(n.progress.fixed=c[0],n.progress.margin=y(c[1])):2===c.length&&h(c[1])?(n.progress.fixed=c[1],n.progress.margin=y(c[0])):1===c.length&&h(c[0])&&(n.progress.fixed=c[0],n.progress.margin=0),"top"===n.progress.fixed?l.css(a.progress_fixed).css("top",n.progress.margin?n.progress.margin.value+(n.progress.margin.fixed?n.progress.margin.units:"%"):0):"bottom"===n.progress.fixed&&l.css(a.progress_fixed).css("top","auto"),t.progressClass?n.progress.bar.addClass(t.progressClass):t.progressColor&&n.progress.bar.css("background",t.progressColor)}t.fade?!0===t.fade?t.fade=i.fade:"string"==typeof t.fade||"number"==typeof t.fade?t.fade=[t.fade,t.fade]:e.isArray(t.fade)&&t.fade.length<2&&(t.fade=[t.fade[0],t.fade[0]]):t.fade=[0,0],t.fade=[parseInt(t.fade[0],10),parseInt(t.fade[1],10)],n.settings=t,r.data("loadingoverlay_data",n),s.data("loadingoverlay",r),r.fadeTo(0,.01).appendTo("body"),m(s,!0),t.resizeInterval>0&&(n.resizeIntervalId=setInterval(function(){m(s,!1)},t.resizeInterval)),r.fadeTo(t.fade[0],1)}n.count++}function l(s,t){var a=f(s=e(s)),o=p(s);!1!==o&&(o.count--,(t||o.count<=0)&&(o.resizeIntervalId&&clearInterval(o.resizeIntervalId),a.fadeOut(o.settings.fade[1],function(){e(this).remove()}),s.removeData("loadingoverlay")))}function g(s){m(e(s),!0)}function c(s,t){var a=p(s=e(s));!1!==a&&a.text&&(!1===t?a.text.hide():a.text.show().text(t))}function d(s,t){var a=p(s=e(s));if(!1!==a&&a.progress)if(!1===t)a.progress.bar.hide();else{var o=100*((parseFloat(t)||0)-a.progress.min)/(a.progress.max-a.progress.min);o<0&&(o=0),o>100&&(o=100),a.progress.bar.show().animate({width:o+"%"},a.progress.speed)}}function m(s,t){var a=f(s),o=p(s);if(!1!==o){if(!o.wholePage){var r="fixed"===s.css("position"),i=r?s[0].getBoundingClientRect():s.offset();a.css({position:r?"fixed":"absolute",top:i.top+parseInt(s.css("border-top-width"),10),left:i.left+parseInt(s.css("border-left-width"),10),width:s.innerWidth(),height:s.innerHeight()})}if(o.settings.size){var n=o.wholePage?e(window):s,l=o.settings.size.value;o.settings.size.fixed||(l=Math.min(n.innerWidth(),n.innerHeight())*l/100,o.settings.maxSize&&l>o.settings.maxSize&&(l=o.settings.maxSize),o.settings.minSize&&l<o.settings.minSize&&(l=o.settings.minSize)),a.children(".loadingoverlay_element").each(function(){var s=e(this);if(t||s.data("loadingoverlay_autoresize")){var a=s.data("loadingoverlay_resizefactor");s.hasClass("loadingoverlay_fa")||s.hasClass("loadingoverlay_text")?s.css("font-size",l*a+o.settings.size.units):s.hasClass("loadingoverlay_progress")?(o.progress.bar.css("height",l*a+o.settings.size.units),o.progress.fixed?"bottom"===o.progress.fixed&&s.css("bottom",o.progress.margin?o.progress.margin.value+(o.progress.margin.fixed?o.progress.margin.units:"%"):0).css("bottom","+="+l*a+o.settings.size.units):o.progress.bar.css("top",s.position().top).css("top","-="+l*a*.5+o.settings.size.units)):s.css({width:l*a+o.settings.size.units,height:l*a+o.settings.size.units})}})}}}function f(e){return e.data("loadingoverlay")}function p(t){var a=f(t),o=void 0===a?s:a.data("loadingoverlay_data");return void 0===o?(e(".loadingoverlay").each(function(){var s=e(this),t=s.data("loadingoverlay_data");document.body.contains(t.container[0])||(t.resizeIntervalId&&clearInterval(t.resizeIntervalId),s.remove())}),!1):(a.toggle(t.is(":visible")),o)}function u(s,t,o,r,n){var l=e("<div>",{class:"loadingoverlay_element",css:{order:t}}).css(a.element).data({loadingoverlay_autoresize:o,loadingoverlay_resizefactor:r}).appendTo(s);if(!0===n&&(n=i.animations.time+" "+i.animations.name),"string"==typeof n){var g,c,d=n.replace(/\s\s+/g," ").toLowerCase().split(" ");2===d.length&&v(d[0])&&x(d[1])?(g=d[1],c=d[0]):2===d.length&&v(d[1])&&x(d[0])?(g=d[0],c=d[1]):1===d.length&&v(d[0])?(g=i.animations.name,c=d[0]):1===d.length&&x(d[0])&&(g=d[0],c=i.animations.time),l.css({"animation-name":"loadingoverlay_animation__"+g,"animation-duration":c,"animation-timing-function":"linear","animation-iteration-count":"infinite"})}return l}function v(e){return!isNaN(parseFloat(e))&&("s"===e.slice(-1)||"ms"===e.slice(-2))}function x(e){return r.animations.indexOf(e)>-1}function h(e){return r.progressPosition.indexOf(e)>-1}function y(e){return!(!e||e<0)&&("string"==typeof e&&["vmin","vmax"].indexOf(e.slice(-4))>-1?{fixed:!0,units:e.slice(-4),value:e.slice(0,-4)}:"string"==typeof e&&["rem"].indexOf(e.slice(-3))>-1?{fixed:!0,units:e.slice(-3),value:e.slice(0,-3)}:"string"==typeof e&&["px","em","cm","mm","in","pt","pc","vh","vw"].indexOf(e.slice(-2))>-1?{fixed:!0,units:e.slice(-2),value:e.slice(0,-2)}:{fixed:!1,units:"px",value:parseFloat(e)})}e.LoadingOverlaySetup=function(s){e.extend(!0,t,s)},e.LoadingOverlay=function(s,a){switch(s.toLowerCase()){case"show":n("body",e.extend(!0,{},t,a));break;case"hide":l("body",a);break;case"resize":g("body");break;case"text":c("body",a);break;case"progress":d("body",a)}},e.fn.LoadingOverlay=function(s,a){switch(s.toLowerCase()){case"show":var o=e.extend(!0,{},t,a);return this.each(function(){n(this,o)});case"hide":return this.each(function(){l(this,a)});case"resize":return this.each(function(){g(this)});case"text":return this.each(function(){c(this,a)});case"progress":return this.each(function(){d(this,a)})}},e(function(){e("head").append(["<style>","@-webkit-keyframes loadingoverlay_animation__rotate_right {","to {","-webkit-transform : rotate(360deg);","transform : rotate(360deg);","}","}","@keyframes loadingoverlay_animation__rotate_right {","to {","-webkit-transform : rotate(360deg);","transform : rotate(360deg);","}","}","@-webkit-keyframes loadingoverlay_animation__rotate_left {","to {","-webkit-transform : rotate(-360deg);","transform : rotate(-360deg);","}","}","@keyframes loadingoverlay_animation__rotate_left {","to {","-webkit-transform : rotate(-360deg);","transform : rotate(-360deg);","}","}","@-webkit-keyframes loadingoverlay_animation__fadein {","0% {","opacity : 0;","-webkit-transform : scale(0.1, 0.1);","transform : scale(0.1, 0.1);","}","50% {","opacity : 1;","}","100% {","opacity : 0;","-webkit-transform : scale(1, 1);","transform : scale(1, 1);","}","}","@keyframes loadingoverlay_animation__fadein {","0% {","opacity : 0;","-webkit-transform : scale(0.1, 0.1);","transform : scale(0.1, 0.1);","}","50% {","opacity : 1;","}","100% {","opacity : 0;","-webkit-transform : scale(1, 1);","transform : scale(1, 1);","}","}","@-webkit-keyframes loadingoverlay_animation__pulse {","0% {","-webkit-transform : scale(0, 0);","transform : scale(0, 0);","}","50% {","-webkit-transform : scale(1, 1);","transform : scale(1, 1);","}","100% {","-webkit-transform : scale(0, 0);","transform : scale(0, 0);","}","}","@keyframes loadingoverlay_animation__pulse {","0% {","-webkit-transform : scale(0, 0);","transform : scale(0, 0);","}","50% {","-webkit-transform : scale(1, 1);","transform : scale(1, 1);","}","100% {","-webkit-transform : scale(0, 0);","transform : scale(0, 0);","}","}","</style>"].join(" "))})});
permalink-manager.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: Permalink Manager Lite
5
  * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6
  * Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
7
- * Version: 2.0.6.3
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
@@ -21,7 +21,7 @@ if (!defined('WPINC')) {
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24
- define( 'PERMALINK_MANAGER_VERSION', '2.0.6.3' );
25
  define( 'PERMALINK_MANAGER_FILE', __FILE__ );
26
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit(dirname(__FILE__)) );
27
  define( 'PERMALINK_MANAGER_BASENAME', dirname(plugin_basename(__FILE__)));
@@ -60,6 +60,7 @@ class Permalink_Manager_Class {
60
  'actions' => 'Permalink_Manager_Actions',
61
  'third-parties' => 'Permalink_Manager_Third_Parties',
62
  'core-functions' => 'Permalink_Manager_Core_Functions',
 
63
  'pro-functions' => 'Permalink_Manager_Pro_Functions'
64
  ),
65
  'views' => array(
@@ -149,6 +150,7 @@ class Permalink_Manager_Class {
149
  ),
150
  'general' => array(
151
  'force_custom_slugs' => 0,
 
152
  'auto_update_uris' => 0,
153
  'setup_redirects' => 1,
154
  'redirect' => '301',
@@ -180,18 +182,18 @@ class Permalink_Manager_Class {
180
  */
181
  public function default_alerts($alerts) {
182
  $default_alerts = apply_filters('permalink-manager-default-alerts', array(
183
- 'spring' => array(
184
  'txt' => sprintf(
185
  __("Get access to extra features: full taxonomy and WooCommerce support, possibility to use custom fields inside the permalinks and more!<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and save %s using \"%s\" coupon code!</strong> Valid until %s!", "permalink-manager"),
186
  PERMALINK_MANAGER_WEBSITE,
187
- '20&#37;',
188
- 'SPRING',
189
- '31.03'
190
  ),
191
  'type' => 'notice-info',
192
  'show' => 'pro_hide',
193
  'plugin_only' => true,
194
- 'until' => '2018-04-01'
195
  )
196
  ));
197
 
4
  * Plugin Name: Permalink Manager Lite
5
  * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6
  * Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
7
+ * Version: 2.1.1
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24
+ define( 'PERMALINK_MANAGER_VERSION', '2.1.1' );
25
  define( 'PERMALINK_MANAGER_FILE', __FILE__ );
26
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit(dirname(__FILE__)) );
27
  define( 'PERMALINK_MANAGER_BASENAME', dirname(plugin_basename(__FILE__)));
60
  'actions' => 'Permalink_Manager_Actions',
61
  'third-parties' => 'Permalink_Manager_Third_Parties',
62
  'core-functions' => 'Permalink_Manager_Core_Functions',
63
+ 'gutenberg' => 'Permalink_Manager_Gutenberg',
64
  'pro-functions' => 'Permalink_Manager_Pro_Functions'
65
  ),
66
  'views' => array(
150
  ),
151
  'general' => array(
152
  'force_custom_slugs' => 0,
153
+ 'show_native_slug_field' => 0,
154
  'auto_update_uris' => 0,
155
  'setup_redirects' => 1,
156
  'redirect' => '301',
182
  */
183
  public function default_alerts($alerts) {
184
  $default_alerts = apply_filters('permalink-manager-default-alerts', array(
185
+ 'october2018' => array(
186
  'txt' => sprintf(
187
  __("Get access to extra features: full taxonomy and WooCommerce support, possibility to use custom fields inside the permalinks and more!<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and save %s using \"%s\" coupon code!</strong> Valid until %s!", "permalink-manager"),
188
  PERMALINK_MANAGER_WEBSITE,
189
+ '30&#37;',
190
+ 'OCTOBER',
191
+ '31st October'
192
  ),
193
  'type' => 'notice-info',
194
  'show' => 'pro_hide',
195
  'plugin_only' => true,
196
+ 'until' => '2018-11-01'
197
  )
198
  ));
199