Permalink Manager Lite - Version 1.1.0

Version Description

  • Partial code refactoring
  • "Auto-update" feature
  • UI/UX improvements
  • Support for AMP plugin by Automattic
Download this release

Release Info

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

Code changes from version 1.0.4 to 1.1.0

README.txt CHANGED
@@ -1,24 +1,31 @@
1
  === Permalink Manager ===
2
  Contributors: mbis
 
3
  License: GPLv3
4
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
5
  Tags: urls, permalinks, slugs, custom url, custom permalinks, uris, url, slug, permalink
6
  Requires at least: 4.0
7
- Tested up to: 4.7.3
8
- Stable tag: 1.0.2
9
 
10
  Most advanced yet easy-to-use permalink plugin that helps to maintain & bulk change your URLs & slugs.
11
 
12
- == Description ==
 
 
13
 
14
  A really intuitive and easy-to-use plugin that helps to manage the permalinks for all your posts, pages and other custom post types items.
15
 
16
  Currently, the plugin allows to perform four main actions:
17
 
18
- 1. It allows to manually adjust selected permalinks (URIs or native slugs) for all posts/pages/custom post type items.
19
  2. It allows to bulk replace particular words used in permalinks (or native slugs) with another words (works also with substring).
20
  3. It allows to bulk regenerate/reset permalinks (or native slugs). This might be especially useful if your post titles are updated and native slugs need to be recreated.
21
  4. It allows to change the default permalink bases (permastructures) for all custom post types & posts and pages.
 
 
 
 
22
 
23
  To improve the user experience, each tool allows also to filter the permalinks by post types or post statuses.
24
 
@@ -38,12 +45,22 @@ http://example.com/poland/cities/poznan === [not changed] ===> http://example.co
38
  = All features =
39
 
40
  * "Permalink Editor" - list of your permalinks (groupped by post types).
 
41
  * "Regenerate/Reset" permalinks, custom and native URIs (slugs).
42
  * "Find and replace" strings in permalinks, custom and native URIs (slugs).
43
  * Support for "Primary Term" functionality implemented in "Yoast SEO" plugin.
44
  * Optional redirect (301 or 302) from old (native) permalinks to new (custom) permalinks.
45
  * Possibility to disable native canonical redirects.
46
 
 
 
 
 
 
 
 
 
 
47
  == Installation ==
48
 
49
  Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`.
@@ -54,7 +71,24 @@ You can also install this plugin manually:
54
  2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory.
55
  3. Activate the plugin through the 'Plugins' menu in WordPress
56
 
 
57
  After the plugin is installed you can access its dashboard from this page: `Tools -> Permalink Manager`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  == Screenshots ==
60
 
@@ -65,13 +99,18 @@ After the plugin is installed you can access its dashboard from this page: `Tool
65
  5. A list of updated posts.
66
  6. Editable URI box in Post/Page/CPT edit pagees.
67
  7. Settings section.
68
- 8. Developer section.
69
 
70
 
71
  == Changelog ==
72
 
73
- = 1.0.4 =
74
- * Additional debug functions added
 
 
 
 
 
 
75
 
76
  = 1.0.2 =
77
  * Post pagination fix
1
  === Permalink Manager ===
2
  Contributors: mbis
3
+ Donate link: https://www.paypal.me/Bismit
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
6
  Tags: urls, permalinks, slugs, custom url, custom permalinks, uris, url, slug, permalink
7
  Requires at least: 4.0
8
+ Tested up to: 4.8
9
+ Stable tag: 1.1.0
10
 
11
  Most advanced yet easy-to-use permalink plugin that helps to maintain & bulk change your URLs & slugs.
12
 
13
+ == Description ==
14
+
15
+ <strong>Follow <a href="https://www.facebook.com/permalinkmanager/" target="_blank">Permalink Manager</a> on Facebook for news & updates!</strong>
16
 
17
  A really intuitive and easy-to-use plugin that helps to manage the permalinks for all your posts, pages and other custom post types items.
18
 
19
  Currently, the plugin allows to perform four main actions:
20
 
21
+ 1. It allows to manually adjust permalinks (URIs) for all posts/pages/custom post type items.
22
  2. It allows to bulk replace particular words used in permalinks (or native slugs) with another words (works also with substring).
23
  3. It allows to bulk regenerate/reset permalinks (or native slugs). This might be especially useful if your post titles are updated and native slugs need to be recreated.
24
  4. It allows to change the default permalink bases (permastructures) for all custom post types & posts and pages.
25
+ 5. It allows to auto-update URIs to match the current permastructure settings after eg. post title or assigned primary category is changed.
26
+ 6. (<a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro</a> only) It allows to manually adjust permalinks (URIs) for all categories/tags/custom terms.
27
+ 7. (<a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro</a> only) It allows to remove /product-category and /product from WooCommerce permalinks.
28
+ 8. (<a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro</a> only) It allows to define custom "stop-words" list and/or use custom one (19 languages available).
29
 
30
  To improve the user experience, each tool allows also to filter the permalinks by post types or post statuses.
31
 
45
  = All features =
46
 
47
  * "Permalink Editor" - list of your permalinks (groupped by post types).
48
+ * "Auto-update" URI
49
  * "Regenerate/Reset" permalinks, custom and native URIs (slugs).
50
  * "Find and replace" strings in permalinks, custom and native URIs (slugs).
51
  * Support for "Primary Term" functionality implemented in "Yoast SEO" plugin.
52
  * Optional redirect (301 or 302) from old (native) permalinks to new (custom) permalinks.
53
  * Possibility to disable native canonical redirects.
54
 
55
+ = Additional features available in Permalink Manager Pro =
56
+
57
+ * Priority support
58
+ * Full support for taxonomies
59
+ * Full support for WooCommerce
60
+ * "Stop-words" to keep your permalinks short & clean (pre-defined "stop-words" lists are available in 19 languages)
61
+
62
+ Buy <a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro here</a>.
63
+
64
  == Installation ==
65
 
66
  Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`.
71
  2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory.
72
  3. Activate the plugin through the 'Plugins' menu in WordPress
73
 
74
+ = Bulk URI editor =
75
  After the plugin is installed you can access its dashboard from this page: `Tools -> Permalink Manager`.
76
+
77
+ = Single URI editor =
78
+ To display the URI editor metabox click on gray "Permalink Editor" displayed below the post/page title.
79
+
80
+ == Frequently Asked Questions ==
81
+
82
+ = Q. Can I delete/disable Permalink Manager after the permalinks are updated? =
83
+ A. Yes, if you used Permalink Manager only to regenerate the slugs (native post names). Please note that if you use custom permalinks (that differ from the native ones), they will no longer be used after the plugin is disabled.
84
+
85
+ It is because Permalink Manager overwrites one of the core Wordpress functionalities to bypass the rewrite rules ("regular expressions" to detect the posts/pages/taxonomies/etc. and another parameters from the URL) by using the array of custom permalinks (you can check them in "Debug" tab) that are used only by my plugin.
86
+
87
+ = Q. Can I use Permalink Manager to alter the permalinks for taxonomies?
88
+ A. This feature will be available in Permalink Manager Pro.
89
+
90
+ = Q. Does this plugin support Buddypress?
91
+ A. Currently there is no 100% guarantee that Permalink Manager will work correctly with Buddypress.
92
 
93
  == Screenshots ==
94
 
99
  5. A list of updated posts.
100
  6. Editable URI box in Post/Page/CPT edit pagees.
101
  7. Settings section.
 
102
 
103
 
104
  == Changelog ==
105
 
106
+ = 1.1.0 =
107
+ * Partial code refactoring
108
+ * "Auto-update" feature
109
+ * UI/UX improvements
110
+ * Support for AMP plugin by Automattic
111
+
112
+ = 1.0.3 =
113
+ * Another pagination issue - hotfix
114
 
115
  = 1.0.2 =
116
  * Post pagination fix
includes/core/permalink-manager-actions.php CHANGED
@@ -7,6 +7,9 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
7
  public function __construct() {
8
  add_action( 'admin_init', array($this, 'trigger_action'), 999 );
9
  add_action( 'admin_init', array($this, 'clear_uris') );
 
 
 
10
  }
11
 
12
  /**
@@ -67,21 +70,45 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
67
  /**
68
  * Save settings
69
  */
70
- public static function save_settings() {
71
- global $permalink_manager_options;
72
 
73
- $post_fields = $_POST;
74
- $new_options = array();
 
75
 
76
- foreach($post_fields as $option_name => $option_value) {
77
- $new_options[$option_name] = $option_value;
 
 
 
 
 
 
 
78
  }
79
 
80
- // Override the global with settings
 
81
  $permalink_manager_options = $new_options = array_filter($new_options);
82
 
83
  // Save the settings in database
84
  update_option('permalink-manager', $new_options);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  /**
@@ -149,7 +176,7 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
149
  */
150
  function find_and_replace() {
151
  // Check if posts or terms should be updated
152
- if(!empty($_POST['section_type']) && $_POST['section_type'] == 'tax') {
153
  return Permalink_Manager_URI_Functions_Tax::find_and_replace();
154
  } else {
155
  return Permalink_Manager_URI_Functions_Post::find_and_replace();
@@ -161,7 +188,7 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
161
  */
162
  function regenerate_all_permalinks() {
163
  // Check if posts or terms should be updated
164
- if(!empty($_POST['section_type']) && $_POST['section_type'] == 'tax') {
165
  return Permalink_Manager_URI_Functions_Tax::regenerate_all_permalinks();
166
  } else {
167
  return Permalink_Manager_URI_Functions_Post::regenerate_all_permalinks();
@@ -173,7 +200,7 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
173
  */
174
  function update_all_permalinks() {
175
  // Check if posts or terms should be updated
176
- if(!empty($_POST['section_type']) && $_POST['section_type'] == 'tax') {
177
  return Permalink_Manager_URI_Functions_Tax::update_all_permalinks();
178
  } else {
179
  return Permalink_Manager_URI_Functions_Post::update_all_permalinks();
7
  public function __construct() {
8
  add_action( 'admin_init', array($this, 'trigger_action'), 999 );
9
  add_action( 'admin_init', array($this, 'clear_uris') );
10
+
11
+ // Screen Options
12
+ add_action( 'admin_init', array($this, 'save_screen_options'), 999 );
13
  }
14
 
15
  /**
70
  /**
71
  * Save settings
72
  */
73
+ public static function save_settings($field = false, $value = false) {
74
+ global $permalink_manager_options, $permalink_manager_before_sections_html;
75
 
76
+ // Info: The settings array is used also by "Screen Options"
77
+ $new_options = $permalink_manager_options;
78
+ //$new_options = array();
79
 
80
+ // Save only selected field/sections
81
+ if($field && $value) {
82
+ $new_options[$field] = $value;
83
+ } else {
84
+ $post_fields = $_POST;
85
+
86
+ foreach($post_fields as $option_name => $option_value) {
87
+ $new_options[$option_name] = $option_value;
88
+ }
89
  }
90
 
91
+ // Sanitize & override the global with new settings
92
+ $new_options = Permalink_Manager_Helper_Functions::sanitize_array($new_options);
93
  $permalink_manager_options = $new_options = array_filter($new_options);
94
 
95
  // Save the settings in database
96
  update_option('permalink-manager', $new_options);
97
+
98
+ // Display the message
99
+ $permalink_manager_before_sections_html .= Permalink_Manager_Admin_Functions::get_alert_message(__( 'The settings are saved!', 'permalink-manager' ), 'updated');
100
+ }
101
+
102
+ /**
103
+ * Save "Screen Options"
104
+ */
105
+ public static function save_screen_options() {
106
+ if(!empty($_POST['screen-options-apply'])) {
107
+ check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
108
+
109
+ // The values will be sanitized inside the function
110
+ self::save_settings('screen-options', $_POST['screen-options']);
111
+ }
112
  }
113
 
114
  /**
176
  */
177
  function find_and_replace() {
178
  // Check if posts or terms should be updated
179
+ if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
180
  return Permalink_Manager_URI_Functions_Tax::find_and_replace();
181
  } else {
182
  return Permalink_Manager_URI_Functions_Post::find_and_replace();
188
  */
189
  function regenerate_all_permalinks() {
190
  // Check if posts or terms should be updated
191
+ if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
192
  return Permalink_Manager_URI_Functions_Tax::regenerate_all_permalinks();
193
  } else {
194
  return Permalink_Manager_URI_Functions_Post::regenerate_all_permalinks();
200
  */
201
  function update_all_permalinks() {
202
  // Check if posts or terms should be updated
203
+ if(!empty($_POST['content_type']) && $_POST['content_type'] == 'taxonomies') {
204
  return Permalink_Manager_URI_Functions_Tax::update_all_permalinks();
205
  } else {
206
  return Permalink_Manager_URI_Functions_Post::update_all_permalinks();
includes/core/permalink-manager-admin-functions.php CHANGED
@@ -12,7 +12,10 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
12
  public function __construct() {
13
  add_action( 'admin_menu', array($this, 'add_menu_page') );
14
  add_action( 'admin_init', array($this, 'init') );
15
- add_action( 'admin_notices', array($this, 'custom_admin_notices') );
 
 
 
16
  }
17
 
18
  /**
@@ -83,14 +86,18 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
83
  * Register the CSS file for the dashboard.
84
  */
85
  public function enqueue_styles() {
86
- wp_enqueue_style( $this->plugin_slug, PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.css', array(), PERMALINK_MANAGER_VERSION, 'all' );
 
87
  }
88
 
89
  /**
90
  * Register the JavaScript file for the dashboard.
91
  */
92
  public function enqueue_scripts() {
93
- wp_enqueue_script( $this->plugin_slug, PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery' ), PERMALINK_MANAGER_VERSION, false );
 
 
 
94
  }
95
 
96
  /**
@@ -104,7 +111,10 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
104
  * Additional links on "Plugins" page
105
  */
106
  public function plugins_page_links($links) {
107
- $links[] = '<a href="' . $this->get_admin_url() .'">' . __( 'Go To Permalink Manager', 'permalink-manager' ) . '</a>';
 
 
 
108
  return $links;
109
  }
110
 
@@ -120,16 +130,24 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
120
  // Allow to filter the $args
121
  $args = apply_filters('permalink-manager-field-args', $args, $input_name);
122
 
 
123
  $default = (isset($args['default'])) ? $args['default'] : '';
124
  $label = (isset($args['label'])) ? $args['label'] : '';
125
- $placeholder = (isset($args['placeholder'])) ? "placeholder=\"{$args['placeholder']}\"" : '';
126
- $readonly = (isset($args['readonly'])) ? "readonly=\"readonly\"" : '';
127
  $rows = (isset($args['rows'])) ? "rows=\"{$rows}\"" : "rows=\"5\"";
128
- $input_class = (isset($args['input_class'])) ? "class=\"{$args['input_class']}\"" : '';
129
  $container_class = (isset($args['container_class'])) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";
130
- $description = (isset($args['description'])) ? "<p class=\"field-description description\">{$args['description']}</p>" : "";
 
 
 
131
  $append_content = (isset($args['append_content'])) ? "{$args['append_content']}" : "";
132
 
 
 
 
 
 
 
 
133
  // Get the field value (if it is not set in $args)
134
  if(isset($args['value']) && empty($args['value']) == false) {
135
  $value = $args['value'];
@@ -146,12 +164,15 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
146
  }
147
  }
148
 
149
- switch($args['type']) {
150
  case 'checkbox' :
151
  $fields .= '<div class="checkboxes">';
152
- foreach($args['choices'] as $choice_value => $checkbox_label) {
153
- $checked = (is_array($value) && in_array($choice_value, $value)) ? "checked='checked'" : "";
154
- $fields .= "<label for='{$input_name}[]'><input type='checkbox' {$input_class} value='{$choice_value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
 
 
 
155
  }
156
  $fields .= '</div>';
157
 
@@ -172,44 +193,55 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
172
  $checked = ($value == 1) ? "checked='checked'" : "";
173
  $checkbox_label = (isset($args['checkbox_label'])) ? $args['checkbox_label'] : '';
174
 
175
- $fields .= "<label for='{$input_name}'><input type='checkbox' {$input_class} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>";
 
176
  $fields .= '</div>';
177
  break;
178
 
179
  case 'radio' :
180
  $fields .= '<div class="radios">';
181
- foreach($args['choices'] as $choice_value => $checkbox_label) {
182
- $checked = ($choice_value == $value) ? "checked='checked'" : "";
183
- $fields .= "<label for='{$input_name}[]'><input type='radio' {$input_class} value='{$choice_value}' name='{$input_name}[]' {$checked} /> {$checkbox_label}</label>";
 
 
 
184
  }
185
  $fields .= '</div>';
186
  break;
187
 
188
  case 'select' :
189
  $fields .= '<div class="select">';
190
- $fields .= "<select name='{$input_name}' {$input_class}>";
191
- foreach($args['choices'] as $choice_value => $checkbox_label) {
192
- $selected = ($choice_value == $value) ? "selected='selected'" : "";
193
- $fields .= "<option value='{$choice_value}' {$selected} />{$checkbox_label}</option>";
 
 
 
194
  }
195
  $fields .= '</select>';
196
  $fields .= '</div>';
197
  break;
198
 
199
  case 'number' :
200
- $fields .= "<input type='number' {$input_class} value='{$value}' name='{$input_name}' />";
201
  break;
202
 
203
  case 'hidden' :
204
- $fields .= "<input type='hidden' {$input_class} value='{$value}' name='{$input_name}' />";
205
  break;
206
 
207
  case 'textarea' :
208
- $fields .= "<textarea {$input_class} name='{$input_name}' {$placeholder} {$readonly} {$rows}>{$value}</textarea>";
209
  break;
210
 
211
  case 'pre' :
212
- $fields .= "<pre {$input_class}>{$value}</pre>";
 
 
 
 
213
  break;
214
 
215
  case 'clearfix' :
@@ -217,55 +249,61 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
217
 
218
  case 'permastruct' :
219
  $siteurl = get_option('home');
220
- $fields .= "<code>{$siteurl}/</code><input type='text' {$input_class} value='{$value}' name='{$input_name}' {$placeholder} {$readonly}/>";
221
  break;
222
 
223
  default :
224
- $fields .= "<input type='text' {$input_class} value='{$value}' name='{$input_name}' {$placeholder} {$readonly}/>";
225
  }
226
 
227
  // Get the final HTML output
228
  if(isset($args['container']) && $args['container'] == 'tools') {
229
- $output = "<div{$container_class}>";
230
- $output .= "<h4>{$label}</h4>";
231
- $output .= "<div class='{$input_name}-container'>{$fields}</div>";
232
- $output .= $description;
233
- $output .= $append_content;
234
- $output .= "</div>";
235
  } else if(isset($args['container']) && $args['container'] == 'row') {
236
- $output = "<tr><th><label for='{$input_name}'>{$args['label']}</label></th>";
237
- $output .= "<td>{$fields}{$description}</td></tr>";
238
- $output .= ($append_content) ? "<tr class=\"appended-row\"><td colspan=\"2\">{$append_content}</td></tr>" : "";
 
 
 
 
 
239
  } else {
240
- $output = $fields . $append_content;
241
  }
242
 
243
- return apply_filters('permalink-manager-field-output', $output);
244
  }
245
 
246
  /**
247
  * Display hidden field to indicate posts or taxonomies admin sections
248
  */
249
  static public function section_type_field($type = 'post') {
250
- return self::generate_option_field('section_type', array('value' => $type, 'type' => 'hidden'));
251
  }
252
 
253
  /**
254
  * Display the form
255
  */
256
- static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array()) {
257
  // 1. Check if the content will be displayed in columns and button details
258
  switch($container) {
259
  case 'columns-3' :
260
- $wrapper_class = 'columns-container';
261
- $form_column_class = 'column column-2_3';
262
- $sidebar_class = 'column column-1_3';
263
- break;
 
264
  // there will be more cases in future ...
265
  default :
266
- $form_column_class = 'form';
267
- $sidebar_class = 'sidebar';
268
- $wrapper_class = $form_column_class = '';
269
  }
270
 
271
  // 2. Process the array with button and nonce field settings
@@ -275,20 +313,21 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
275
  $nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : '';
276
 
277
  // 2. Now get the HTML output (start section row container)
278
- $output = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : '';
279
 
280
  // 3. Display some notes
281
  if($sidebar_class && $sidebar) {
282
- $output .= "<div class=\"{$sidebar_class}\">";
283
- $output .= "<div class=\"section-notes\">";
284
- $output .= $sidebar;
285
- $output .= "</div>";
286
- $output .= "</div>";
287
  }
288
 
289
  // 4. Start fields' section
290
- $output .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : "";
291
- $output .= "<form method=\"POST\">";
 
292
 
293
  // Loop through all fields assigned to this section
294
  foreach($fields as $field_name => $field) {
@@ -296,10 +335,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
296
 
297
  // A. Display table row
298
  if(isset($field['container']) && $field['container'] == 'row') {
299
- $output .= (isset($field['section_name'])) ? "<h3>{$field['section_name']}</h3>" : "";
300
- $output .= (isset($field['description'])) ? "<p class=\"description\">{$field['description']}</p>" : "";
301
- $output .= (isset($field['append_content'])) ? $field['append_content'] : "";
302
- $output .= "<table class=\"form-table\">";
303
 
304
  // Loop through all fields assigned to this section
305
  if(isset($field['fields'])) {
@@ -307,30 +343,39 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
307
  $section_field_name = (!empty($section_field['name'])) ? $section_field['name'] : "{$field_name}[$section_field_id]";
308
  $section_field['container'] = 'row';
309
 
310
- $output .= self::generate_option_field($section_field_name, $section_field);
311
  }
312
  } else {
313
- $output .= self::generate_option_field($field_name, $field);
314
  }
315
 
316
- $output .= "</table>";
 
 
 
 
 
 
 
317
  }
318
  // B. Display single field
319
  else {
320
- $output .= self::generate_option_field($field_name, $field);
321
  }
322
  }
323
 
 
 
324
  // End the fields' section + add button & nonce fields
325
- $output .= ($nonce_action && $nonce_name) ? wp_nonce_field($nonce_action, $nonce_name, true, true) : "";
326
- $output .= ($button_text) ? get_submit_button($button_text, $button_class, '', false) : "";
327
- $output .= '</form>';
328
- $output .= ($form_column_class) ? "</div>" : "";
329
 
330
  // 5. End the section row container
331
- $output .= ($wrapper_class) ? "</div>" : "";
332
 
333
- return $output;
334
  }
335
 
336
  /**
@@ -339,36 +384,38 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
339
  public function display_section() {
340
  global $wpdb, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
341
 
342
- $output = "<div id=\"permalink-manager\" class=\"wrap\">";
343
 
344
- // Display alerts [moved to custom_admin_notices() function] and another content if needed and the plugin header
345
- // $output .= $permalink_manager_before_sections_html;
346
- $output .= "<h2 id=\"plugin-name-heading\">" . PERMALINK_MANAGER_PLUGIN_NAME . " <a href=\"" . PERMALINK_MANAGER_WEBSITE ."\" target=\"_blank\">" . __('by Maciej Bis', 'permalink-manager') . "</a></h2>";
 
 
347
 
348
  // Display the tab navigation
349
- $output .= "<div id=\"permalink-manager-tab-nav\" class=\"nav-tab-wrapper\">";
350
  foreach($this->sections as $section_name => $section_properties) {
351
  $active_class = ($this->active_section === $section_name) ? 'nav-tab-active nav-tab' : 'nav-tab';
352
  $section_url = $this->get_admin_url("&section={$section_name}");
353
 
354
- $output .= "<a href=\"{$section_url}\" class=\"{$active_class}\">{$section_properties['name']}</a>";
355
  }
356
- $output .= "</div>";
357
 
358
  // Now display the active section
359
- $output .= "<div id=\"permalink-manager-sections\">";
360
  $active_section_array = (isset($this->sections[$this->active_section])) ? $this->sections[$this->active_section] : "";
361
 
362
  // Display addidional navigation for subsections
363
  if(isset($this->sections[$this->active_section]['subsections'])) {
364
- $output .= "<ul class=\"subsubsub\">";
365
  foreach ($this->sections[$this->active_section]['subsections'] as $subsection_name => $subsection) {
366
  $active_class = ($this->active_subsection === $subsection_name) ? 'current' : '';
367
  $subsection_url = $this->get_admin_url("&section={$this->active_section}&subsection={$subsection_name}");
368
 
369
- $output .= "<li><a href=\"{$subsection_url}\" class=\"{$active_class}\">{$subsection['name']}</a></li>";
370
  }
371
- $output .= "</ul>";
372
  }
373
 
374
  // A. Execute the function assigned to the subsection
@@ -394,29 +441,40 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
394
  $section_content = (isset($active_section_array['html'])) ? $active_section_array['html'] : "";
395
  }
396
 
397
- $output .= "<div data-section=\"{$this->active_section}\" id=\"{$this->active_section}\">{$section_content}</div>";
398
- $output .= "</div>";
399
 
400
  // Display alerts and another content if needed and close .wrap container
401
- $output .= $permalink_manager_after_sections_html;
402
- $output .= "</div>";
403
 
404
- echo $output;
405
  }
406
 
407
  /**
408
  * Display error/info message
409
  */
410
- public static function get_alert_message($alert_content, $alert_type, $dismissable = true) {
411
  $class = ($dismissable) ? "is-dismissible" : "";
412
- $output = sprintf( "<div class=\"{$alert_type} notice {$class}\"> %s</div>", wpautop($alert_content) );
413
 
414
- return $output;
 
 
415
  }
416
 
417
- static function pro_text() {
418
- $output = sprintf( "<div class=\"alert info\"> %s</div>", wpautop(__('This functionality is available only in "Permalink Manager Pro".'), 'alert', false) );
419
- return $output;
 
 
 
 
 
 
 
 
 
420
  }
421
 
422
  /**
@@ -440,10 +498,17 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
440
  // Odd/even class
441
  $updated_slugs_count++;
442
  $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
443
- $permalink = get_permalink($row['ID']);
 
 
 
 
 
 
 
444
 
445
  $main_content .= "<tr{$alternate_class}>";
446
- $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['post_title'] . "<a target=\"_blank\" href=\"{$permalink}\"><span class=\"small\">{$permalink}</span></a>" . '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __('Show more details', 'permalink-manager') . '</span></button></td>';
447
  $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . $row['old_uri'] . '</td>';
448
  $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . $row['new_uri'] . '</td>';
449
  $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . $row['old_slug'] . '</td>' : "";
@@ -452,16 +517,51 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
452
  }
453
 
454
  // Merge header, footer and content
455
- $output = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
456
- $output .= '<table class="widefat wp-list-table updated-slugs-table">';
457
- $output .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
458
- $output .= '</table>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
 
460
- return $output;
461
  }
462
 
463
- function custom_admin_notices() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  global $permalink_manager_before_sections_html;
 
465
  echo $permalink_manager_before_sections_html;
466
  }
467
 
12
  public function __construct() {
13
  add_action( 'admin_menu', array($this, 'add_menu_page') );
14
  add_action( 'admin_init', array($this, 'init') );
15
+
16
+ add_action( 'admin_notices', array($this, 'display_plugin_notices'));
17
+ add_action( 'admin_notices', array($this, 'display_global_notices'));
18
+ add_action( 'wp_ajax_dismissed_notice_handler', array($this, 'hide_global_notice') );
19
  }
20
 
21
  /**
86
  * Register the CSS file for the dashboard.
87
  */
88
  public function enqueue_styles() {
89
+ wp_enqueue_style( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.css', array(), PERMALINK_MANAGER_VERSION, 'all' );
90
+ wp_enqueue_style( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.css', array('permalink-manager-plugins'), PERMALINK_MANAGER_VERSION, 'all' );
91
  }
92
 
93
  /**
94
  * Register the JavaScript file for the dashboard.
95
  */
96
  public function enqueue_scripts() {
97
+ wp_enqueue_script( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.js', array( 'jquery', ), PERMALINK_MANAGER_VERSION, false );
98
+ wp_enqueue_script( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery', 'permalink-manager-plugins' ), PERMALINK_MANAGER_VERSION, false );
99
+
100
+ wp_localize_script( 'permalink-manager', 'permalink_manager', array('url' => PERMALINK_MANAGER_URL) );
101
  }
102
 
103
  /**
111
  * Additional links on "Plugins" page
112
  */
113
  public function plugins_page_links($links) {
114
+ $links[] = sprintf('<a href="%s">%s</a>', $this->get_admin_url(), __( 'URI Editor', 'permalink-manager' ));
115
+ if(!defined('PERMALINK_MANAGER_PRO') || PERMALINK_MANAGER_PRO !== true) {
116
+ $links[] = sprintf('<a href="%s" target="_blank">%s</a>', PERMALINK_MANAGER_WEBSITE, __( 'Buy Permalink Manager Pro', 'permalink-manager' ));
117
+ }
118
  return $links;
119
  }
120
 
130
  // Allow to filter the $args
131
  $args = apply_filters('permalink-manager-field-args', $args, $input_name);
132
 
133
+ $field_type = (isset($args['type'])) ? $args['type'] : 'text';
134
  $default = (isset($args['default'])) ? $args['default'] : '';
135
  $label = (isset($args['label'])) ? $args['label'] : '';
 
 
136
  $rows = (isset($args['rows'])) ? "rows=\"{$rows}\"" : "rows=\"5\"";
 
137
  $container_class = (isset($args['container_class'])) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";
138
+ $description = (isset($args['before_description'])) ? $args['before_description'] : "";
139
+ $description .= (isset($args['description'])) ? "<p class=\"field-description description\">{$args['description']}</p>" : "";
140
+ $description .= (isset($args['after_description'])) ? $args['after_description'] : "";
141
+ $description .= (isset($args['pro'])) ? sprintf("<p class=\"field-description description\">%s</p>", strip_tags(Permalink_Manager_Admin_Functions::pro_text(true))) : "";
142
  $append_content = (isset($args['append_content'])) ? "{$args['append_content']}" : "";
143
 
144
+ // Input attributes
145
+ $input_atts = (isset($args['input_class'])) ? "class='{$args['input_class']}'" : '';
146
+ $input_atts .= (isset($args['readonly'])) ? " readonly='readonly'" : '';
147
+ $input_atts .= (isset($args['disabled'])) ? " disabled='disabled'" : '';
148
+ $input_atts .= (isset($args['placeholder'])) ? " placeholder='{$args['placeholder']}'" : '';
149
+ $input_atts .= (isset($args['extra_atts'])) ? " {$args['extra_atts']}" : '';
150
+
151
  // Get the field value (if it is not set in $args)
152
  if(isset($args['value']) && empty($args['value']) == false) {
153
  $value = $args['value'];
164
  }
165
  }
166
 
167
+ switch($field_type) {
168
  case 'checkbox' :
169
  $fields .= '<div class="checkboxes">';
170
+ foreach($args['choices'] as $choice_value => $choice) {
171
+ $label = (is_array($choice)) ? $choice['label'] : $choice;
172
+ $atts = (is_array($value) && in_array($choice_value, $value)) ? "checked='checked'" : "";
173
+ $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
174
+
175
+ $fields .= "<label for='{$input_name}[]'><input type='checkbox' {$input_atts} value='{$choice_value}' name='{$input_name}[]' {$atts} /> {$label}</label>";
176
  }
177
  $fields .= '</div>';
178
 
193
  $checked = ($value == 1) ? "checked='checked'" : "";
194
  $checkbox_label = (isset($args['checkbox_label'])) ? $args['checkbox_label'] : '';
195
 
196
+ $fields .= "<input type='hidden' {$input_atts} value='0' name='{$input_name}' checked=\"checked\" />";
197
+ $fields .= "<label for='{$input_name}'><input type='checkbox' {$input_atts} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>";
198
  $fields .= '</div>';
199
  break;
200
 
201
  case 'radio' :
202
  $fields .= '<div class="radios">';
203
+ foreach($args['choices'] as $choice_value => $choice) {
204
+ $label = (is_array($choice)) ? $choice['label'] : $choice;
205
+ $atts = ($choice_value == $value) ? "checked='checked'" : "";
206
+ $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
207
+
208
+ $fields .= "<label for='{$input_name}[]'><input type='radio' {$input_atts} value='{$choice_value}' name='{$input_name}[]' {$atts} /> {$label}</label>";
209
  }
210
  $fields .= '</div>';
211
  break;
212
 
213
  case 'select' :
214
  $fields .= '<div class="select">';
215
+ $fields .= "<select name='{$input_name}' {$input_atts}>";
216
+ foreach($args['choices'] as $choice_value => $choice) {
217
+ $label = (is_array($choice)) ? $choice['label'] : $choice;
218
+ $atts = ($choice_value == $value) ? "selected='selected'" : "";
219
+ $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
220
+
221
+ $fields .= "<option value='{$choice_value}' {$atts} />{$label}</option>";
222
  }
223
  $fields .= '</select>';
224
  $fields .= '</div>';
225
  break;
226
 
227
  case 'number' :
228
+ $fields .= "<input type='number' {$input_atts} value='{$value}' name='{$input_name}' />";
229
  break;
230
 
231
  case 'hidden' :
232
+ $fields .= "<input type='hidden' {$input_atts} value='{$value}' name='{$input_name}' />";
233
  break;
234
 
235
  case 'textarea' :
236
+ $fields .= "<textarea {$input_atts} name='{$input_name}' {$rows}>{$value}</textarea>";
237
  break;
238
 
239
  case 'pre' :
240
+ $fields .= "<pre {$input_atts}>{$value}</pre>";
241
+ break;
242
+
243
+ case 'info' :
244
+ $fields .= "<div {$input_atts}>{$value}</div>";
245
  break;
246
 
247
  case 'clearfix' :
249
 
250
  case 'permastruct' :
251
  $siteurl = get_option('home');
252
+ $fields .= "<code>{$siteurl}/</code><input type='text' {$input_atts} value='{$value}' name='{$input_name}'/>";
253
  break;
254
 
255
  default :
256
+ $fields .= "<input type='text' {$input_atts} value='{$value}' name='{$input_name}'/>";
257
  }
258
 
259
  // Get the final HTML output
260
  if(isset($args['container']) && $args['container'] == 'tools') {
261
+ $html = "<div{$container_class}>";
262
+ $html .= "<h4>{$label}</h4>";
263
+ $html .= "<div class='{$input_name}-container'>{$fields}</div>";
264
+ $html .= $description;
265
+ $html .= $append_content;
266
+ $html .= "</div>";
267
  } else if(isset($args['container']) && $args['container'] == 'row') {
268
+ $html = "<tr data-field=\"{$input_name}\" {$container_class}><th><label for='{$input_name}'>{$args['label']}</label></th>";
269
+ $html .= "<td>{$fields}{$description}</td></tr>";
270
+ $html .= ($append_content) ? "<tr class=\"appended-row\"><td colspan=\"2\">{$append_content}</td></tr>" : "";
271
+ } else if(isset($args['container']) && $args['container'] == 'screen-options') {
272
+ $html = "<fieldset data-field=\"{$input_name}\" {$container_class}><legend>{$args['label']}</legend>";
273
+ $html .= "<div class=\"field-content\">{$fields}{$description}</div>";
274
+ $html .= ($append_content) ? "<div class=\"appended-row\">{$append_content}</div>" : "";
275
+ $html .= "</fieldset>";
276
  } else {
277
+ $html = $fields . $append_content;
278
  }
279
 
280
+ return apply_filters('permalink-manager-field-output', $html);
281
  }
282
 
283
  /**
284
  * Display hidden field to indicate posts or taxonomies admin sections
285
  */
286
  static public function section_type_field($type = 'post') {
287
+ return self::generate_option_field('content_type', array('value' => $type, 'type' => 'hidden'));
288
  }
289
 
290
  /**
291
  * Display the form
292
  */
293
+ static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array(), $wrap = false) {
294
  // 1. Check if the content will be displayed in columns and button details
295
  switch($container) {
296
  case 'columns-3' :
297
+ $wrapper_class = 'columns-container';
298
+ $form_column_class = 'column column-2_3';
299
+ $sidebar_class = 'column column-1_3';
300
+ break;
301
+
302
  // there will be more cases in future ...
303
  default :
304
+ $form_column_class = 'form';
305
+ $sidebar_class = 'sidebar';
306
+ $wrapper_class = $form_column_class = '';
307
  }
308
 
309
  // 2. Process the array with button and nonce field settings
313
  $nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : '';
314
 
315
  // 2. Now get the HTML output (start section row container)
316
+ $html = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : '';
317
 
318
  // 3. Display some notes
319
  if($sidebar_class && $sidebar) {
320
+ $html .= "<div class=\"{$sidebar_class}\">";
321
+ $html .= "<div class=\"section-notes\">";
322
+ $html .= $sidebar;
323
+ $html .= "</div>";
324
+ $html .= "</div>";
325
  }
326
 
327
  // 4. Start fields' section
328
+ $html .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : "";
329
+ $html .= "<form method=\"POST\">";
330
+ $html .= ($wrap) ? "<table class=\"form-table\">" : "";
331
 
332
  // Loop through all fields assigned to this section
333
  foreach($fields as $field_name => $field) {
335
 
336
  // A. Display table row
337
  if(isset($field['container']) && $field['container'] == 'row') {
338
+ $row_output = "";
 
 
 
339
 
340
  // Loop through all fields assigned to this section
341
  if(isset($field['fields'])) {
343
  $section_field_name = (!empty($section_field['name'])) ? $section_field['name'] : "{$field_name}[$section_field_id]";
344
  $section_field['container'] = 'row';
345
 
346
+ $row_output .= self::generate_option_field($section_field_name, $section_field);
347
  }
348
  } else {
349
+ $row_output .= self::generate_option_field($field_name, $field);
350
  }
351
 
352
+ if(isset($field['section_name'])) {
353
+ $html .= "<h3>{$field['section_name']}</h3>";
354
+ $html .= (isset($field['append_content'])) ? $field['append_content'] : "";
355
+ $html .= (isset($field['description'])) ? "<p class=\"description\">{$field['description']}</p>" : "";
356
+ $html .= "<table class=\"form-table\" data-field=\"{$field_name}\">{$row_output}</table>";
357
+ } else {
358
+ $html .= $row_output;
359
+ }
360
  }
361
  // B. Display single field
362
  else {
363
+ $html .= self::generate_option_field($field_name, $field);
364
  }
365
  }
366
 
367
+ $html .= ($wrap) ? "</table>" : "";
368
+
369
  // End the fields' section + add button & nonce fields
370
+ $html .= ($nonce_action && $nonce_name) ? wp_nonce_field($nonce_action, $nonce_name, true, true) : "";
371
+ $html .= ($button_text) ? get_submit_button($button_text, $button_class, '', false) : "";
372
+ $html .= '</form>';
373
+ $html .= ($form_column_class) ? "</div>" : "";
374
 
375
  // 5. End the section row container
376
+ $html .= ($wrapper_class) ? "</div>" : "";
377
 
378
+ return $html;
379
  }
380
 
381
  /**
384
  public function display_section() {
385
  global $wpdb, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
386
 
387
+ $html = "<div id=\"permalink-manager\" class=\"wrap\">";
388
 
389
+ // Display alerts [moved to display_plugin_notices() function] and another content if needed and the plugin header
390
+ // $html .= $permalink_manager_before_sections_html;
391
+ $buy_link = (!defined('PERMALINK_MANAGER_PRO')) ? sprintf("<a href=\"%s\" target=\"_blank\" class=\"page-title-action\">%s</a>", PERMALINK_MANAGER_WEBSITE, __("Buy Permalink Manager Pro", "permalink-manager")) : "";
392
+ $donate_link = sprintf("<a href=\"%s\" target=\"_blank\" class=\"page-title-action\">%s</a>", PERMALINK_MANAGER_DONATE, __("Donate", "permalink-manager"));
393
+ $html .= sprintf("<h2 id=\"plugin-name-heading\">%s <a href=\"http://maciejbis.net\" class=\"author-link\" target=\"_blank\">%s</a> %s %s</h2>", PERMALINK_MANAGER_PLUGIN_NAME, __("by Maciej Bis", "permalink-manager"), $buy_link, $donate_link);
394
 
395
  // Display the tab navigation
396
+ $html .= "<div id=\"permalink-manager-tab-nav\" class=\"nav-tab-wrapper\">";
397
  foreach($this->sections as $section_name => $section_properties) {
398
  $active_class = ($this->active_section === $section_name) ? 'nav-tab-active nav-tab' : 'nav-tab';
399
  $section_url = $this->get_admin_url("&section={$section_name}");
400
 
401
+ $html .= "<a href=\"{$section_url}\" class=\"{$active_class} section_{$section_name}\">{$section_properties['name']}</a>";
402
  }
403
+ $html .= "</div>";
404
 
405
  // Now display the active section
406
+ $html .= "<div id=\"permalink-manager-sections\">";
407
  $active_section_array = (isset($this->sections[$this->active_section])) ? $this->sections[$this->active_section] : "";
408
 
409
  // Display addidional navigation for subsections
410
  if(isset($this->sections[$this->active_section]['subsections'])) {
411
+ $html .= "<ul class=\"subsubsub\">";
412
  foreach ($this->sections[$this->active_section]['subsections'] as $subsection_name => $subsection) {
413
  $active_class = ($this->active_subsection === $subsection_name) ? 'current' : '';
414
  $subsection_url = $this->get_admin_url("&section={$this->active_section}&subsection={$subsection_name}");
415
 
416
+ $html .= "<li><a href=\"{$subsection_url}\" class=\"{$active_class}\">{$subsection['name']}</a></li>";
417
  }
418
+ $html .= "</ul>";
419
  }
420
 
421
  // A. Execute the function assigned to the subsection
441
  $section_content = (isset($active_section_array['html'])) ? $active_section_array['html'] : "";
442
  }
443
 
444
+ $html .= "<div class=\"single-section\" data-section=\"{$this->active_section}\" id=\"{$this->active_section}\">{$section_content}</div>";
445
+ $html .= "</div>";
446
 
447
  // Display alerts and another content if needed and close .wrap container
448
+ $html .= $permalink_manager_after_sections_html;
449
+ $html .= "</div>";
450
 
451
+ echo $html;
452
  }
453
 
454
  /**
455
  * Display error/info message
456
  */
457
+ public static function get_alert_message($alert_content, $alert_type, $dismissable = true, $id = false) {
458
  $class = ($dismissable) ? "is-dismissible" : "";
459
+ $alert_id = ($id) ? " data-alert_id=\"{$id}\"" : "";
460
 
461
+ $html = sprintf( "<div class=\"{$alert_type} permalink-manager-notice notice {$class}\"{$alert_id}> %s</div>", wpautop($alert_content) );
462
+
463
+ return $html;
464
  }
465
 
466
+ static function pro_text($text_only = false) {
467
+ $text = sprintf(__('This functionality is available only in <a href="%s" target="_blank">Permalink Manager Pro</a>.', 'permalink-manager'), PERMALINK_MANAGER_WEBSITE);
468
+
469
+ return ($text_only) ? $text : sprintf("<div class=\"alert info\"> %s</div>", wpautop($text, 'alert', false));
470
+ }
471
+
472
+ /**
473
+ * Help tooltip
474
+ */
475
+ static function help_tooltip($text = '') {
476
+ $html = " <a href=\"#\" title=\"{$text}\" class=\"help_tooltip\"><span class=\"dashicons dashicons-editor-help\"></span></a>";
477
+ return $html;
478
  }
479
 
480
  /**
498
  // Odd/even class
499
  $updated_slugs_count++;
500
  $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
501
+
502
+ // Taxonomy
503
+ if(!empty($row['tax'])) {
504
+ $term_link = get_term_link(intval($row['ID']), $row['tax']);
505
+ $permalink = (is_wp_error($term_link)) ? "-" : $term_link;
506
+ } else {
507
+ $permalink = get_permalink($row['ID']);
508
+ }
509
 
510
  $main_content .= "<tr{$alternate_class}>";
511
+ $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>';
512
  $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . $row['old_uri'] . '</td>';
513
  $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . $row['new_uri'] . '</td>';
514
  $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . $row['old_slug'] . '</td>' : "";
517
  }
518
 
519
  // Merge header, footer and content
520
+ $html = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
521
+ $html .= '<table class="widefat wp-list-table updated-slugs-table">';
522
+ $html .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
523
+ $html .= '</table>';
524
+
525
+ return $html;
526
+ }
527
+
528
+ /**
529
+ * Display global notices (throughout wp-admin dashboard)
530
+ */
531
+ function display_global_notices() {
532
+ global $permalink_manager_alerts;
533
+
534
+ $html = "";
535
+ if(!empty($permalink_manager_alerts) && is_array($permalink_manager_alerts)) {
536
+ foreach($permalink_manager_alerts as $alert_id => $alert) {
537
+ $html .= (!empty($alert['show'])) ? self::get_alert_message($alert['txt'], $alert['type'], true, $alert_id) : "";
538
+ }
539
+ }
540
 
541
+ echo $html;
542
  }
543
 
544
+ /**
545
+ * Hide global notices (AJAX)
546
+ */
547
+ function hide_global_notice() {
548
+ global $permalink_manager_alerts;
549
+
550
+ // Get the ID of the alert
551
+ $alert_id = (!empty($_REQUEST['alert_id'])) ? sanitize_title($_REQUEST['alert_id']) : "";
552
+ if(!empty($permalink_manager_alerts[$alert_id])) {
553
+ $permalink_manager_alerts[$alert_id]['show'] = 0;
554
+ }
555
+
556
+ update_option( 'permalink-manager-alerts', $permalink_manager_alerts);
557
+ }
558
+
559
+ /**
560
+ * Display notices generated by Permalink Manager tools
561
+ */
562
+ function display_plugin_notices() {
563
  global $permalink_manager_before_sections_html;
564
+
565
  echo $permalink_manager_before_sections_html;
566
  }
567
 
includes/core/permalink-manager-helper-functions.php CHANGED
@@ -179,4 +179,23 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
179
  return $def_lang;
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
179
  return $def_lang;
180
  }
181
 
182
+ /**
183
+ * Sanitize multidimensional array
184
+ */
185
+ static function sanitize_array($data = array()) {
186
+ if (!is_array($data) || !count($data)) {
187
+ return array();
188
+ }
189
+
190
+ foreach ($data as $k => $v) {
191
+ if (!is_array($v) && !is_object($v)) {
192
+ $data[$k] = htmlspecialchars(trim($v));
193
+ }
194
+ if (is_array($v)) {
195
+ $data[$k] = self::sanitize_array($v);
196
+ }
197
+ }
198
+ return $data;
199
+ }
200
+
201
  }
includes/core/permalink-manager-third-parties.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Third parties integration
5
+ */
6
+ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
7
+
8
+ public function __construct() {
9
+ add_action('init', array($this, 'wpml_hooks'), 99);
10
+ add_action('init', array($this, 'amp_hooks'), 99);
11
+ }
12
+
13
+ /**
14
+ * 1. WPML filters
15
+ */
16
+ function wpml_hooks() {
17
+ global $sitepress_settings;
18
+
19
+ // Detect Post/Term function
20
+ add_filter('permalink-manager-detected-post-id', array($this, 'wpml_language_mismatch_fix'), 9, 2);
21
+ add_filter('permalink-manager-detected-term-id', array($this, 'wpml_language_mismatch_fix'), 9, 2);
22
+
23
+ // URI Editor
24
+ add_filter('permalink-manager-uri-editor-columns', array($this, 'wpml_lang_column_uri_editor'), 9, 1);
25
+ add_filter('permalink-manager-uri-editor-column-content', array($this, 'wpml_lang_column_content_uri_editor'), 9, 3);
26
+
27
+ // Split the current URL into subparts (check if WPML is active)
28
+ if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
29
+ add_filter('permalink-manager-detect-uri', array($this, 'wpml_detect_post'), 9, 2);
30
+ add_filter('permalink-manager-post-permalink-prefix', array($this, 'wpml_element_lang_prefix'), 9, 3);
31
+ add_filter('permalink-manager-term-permalink-prefix', array($this, 'wpml_element_lang_prefix'), 9, 3);
32
+ }
33
+ }
34
+
35
+ function wpml_language_mismatch_fix($item_id, $uri_parts) {
36
+ $lang_details = apply_filters('wpml_post_language_details', NULL, $item_id);
37
+
38
+ if(is_array($lang_details) && !empty($uri_parts['lang'])) {
39
+ $language_code = (!empty($lang_details['language_code'])) ? $lang_details['language_code'] : '';
40
+ if($uri_parts['lang'] && ($uri_parts['lang'] != $language_code)) {
41
+ $wpml_item_id = apply_filters('wpml_object_id', $item_id);
42
+ $item_id = (is_numeric($wpml_item_id)) ? $wpml_item_id : $item_id;
43
+ }
44
+ }
45
+
46
+ return $item_id;
47
+ }
48
+
49
+ function wpml_detect_post($uri_parts, $request_url) {
50
+ preg_match("/^(?:(\w{2})\/)?(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $regex_parts);
51
+
52
+ $uri_parts['lang'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
53
+ $uri_parts['uri'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
54
+ $uri_parts['endpoint'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
55
+ $uri_parts['endpoint_value'] = (!empty($regex_parts[4])) ? $regex_parts[4] : "";
56
+
57
+ return $uri_parts;
58
+ }
59
+
60
+ function wpml_element_lang_prefix($prefix, $element, $edit_uri_box = false) {
61
+ global $sitepress_settings;
62
+
63
+ if(isset($element->post_type)) {
64
+ $post = (is_integer($element)) ? get_post($element) : $element;
65
+ $lang_details = apply_filters('wpml_element_language_details', NULL, array('element_id' => $post->ID, 'element_type' => $post->post_type));
66
+ } else {
67
+ $term = (is_numeric($element)) ? get_term(intval($element)) : $element;
68
+ $lang_details = apply_filters('wpml_element_language_details', NULL, array('element_id' => $term->term_id, 'element_type' => $term->taxonomy));
69
+ }
70
+
71
+ $prefix = (!empty($lang_details->language_code)) ? $lang_details->language_code : '';
72
+
73
+ if($edit_uri_box) {
74
+ // Last instance - use language paramater from &_GET array
75
+ $prefix = (empty($prefix) && !empty($_GET['lang'])) ? $_GET['lang'] : $prefix;
76
+ }
77
+
78
+ // Append slash to the end of language code if it is not empty
79
+ if(!empty($prefix)) {
80
+ $prefix = "{$prefix}/";
81
+
82
+ // Hide language code if "Use directory for default language" option is enabled
83
+ $default_language = Permalink_Manager_Helper_Functions::get_language();
84
+ if(isset($sitepress_settings['urls']['directory_for_default_language']) && ($sitepress_settings['urls']['directory_for_default_language'] == 0) && ($default_language == $lang_details->language_code)) {
85
+ $prefix = "";
86
+ }
87
+ }
88
+
89
+ return $prefix;
90
+ }
91
+
92
+ function wpml_lang_column_uri_editor($columns) {
93
+ if(class_exists('SitePress')) {
94
+ $columns['post_lang'] = __('Language', 'permalink-manager');
95
+ }
96
+
97
+ return $columns;
98
+ }
99
+
100
+ function wpml_lang_column_content_uri_editor($output, $column, $item) {
101
+ if($column == 'post_lang') {
102
+ if(isset($item->post_type)) {
103
+ $post = (is_integer($item)) ? get_post($item) : $item;
104
+ $lang_details = apply_filters('wpml_element_language_details', NULL, array('element_id' => $post->ID, 'element_type' => $post->post_type));
105
+ } else {
106
+ $term = (is_integer($item)) ? get_term(intval($item)) : $item;
107
+ $lang_details = apply_filters('wpml_element_language_details', NULL, array('element_id' => $term->term_id, 'element_type' => $term->taxonomy));
108
+ }
109
+
110
+ return (!empty($lang_details->language_code)) ? $lang_details->language_code : "-";
111
+ }
112
+
113
+ return $output;
114
+ }
115
+
116
+ /**
117
+ * 2. AMP hooks
118
+ */
119
+ function amp_hooks() {
120
+ if(defined('AMP_QUERY_VAR')) {
121
+ // Detect AMP endpoint
122
+ add_filter('permalink-manager-detect-uri', array($this, 'detect_amp'), 10, 2);
123
+ add_filter('request', array($this, 'enable_amp'), 10, 1);
124
+ }
125
+ }
126
+
127
+ function detect_amp($uri_parts, $request_url) {
128
+ global $amp_enabled;
129
+ $amp_query_var = AMP_QUERY_VAR;
130
+
131
+ // Check if AMP should be triggered
132
+ preg_match("/^(.+?)\/?({$amp_query_var})?\/?$/i", $uri_parts['uri'], $regex_parts);
133
+ if(!empty($regex_parts[2])) {
134
+ $uri_parts['uri'] = $regex_parts[1];
135
+ $amp_enabled = true;
136
+ }
137
+
138
+ return $uri_parts;
139
+ }
140
+
141
+ function enable_amp($query) {
142
+ global $amp_enabled;
143
+
144
+ if(!empty($amp_enabled)) {
145
+ $query[AMP_QUERY_VAR] = 1;
146
+ }
147
+
148
+ return $query;
149
+ }
150
+
151
+ }
152
+ ?>
includes/core/permalink-manager-uri-functions-post.php CHANGED
@@ -7,7 +7,6 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
7
 
8
  public function __construct() {
9
  add_filter( 'get_sample_permalink_html', array($this, 'edit_uri_box'), 999, 5 );
10
- add_action( 'post_submitbox_misc_actions', array($this, 'display_post_link'), 99);
11
 
12
  add_filter( '_get_page_link', array($this, 'custom_post_permalinks'), 999, 2);
13
  add_filter( 'page_link', array($this, 'custom_post_permalinks'), 999, 2);
@@ -15,15 +14,17 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
15
  add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 999, 2);
16
 
17
  add_filter( 'permalink-manager-uris', array($this, 'exclude_homepage'), 999, 2);
18
- add_action( 'save_post', array($this, 'update_post_uri'), 10, 3 );
19
  add_action( 'wp_trash_post', array($this, 'remove_post_uri'), 10, 3 );
 
 
20
  }
21
 
22
  /**
23
  * Change permalinks for posts, pages & custom post types
24
  */
25
  function custom_post_permalinks($permalink, $post) {
26
- global $wp_rewrite, $permalink_manager_uris, $sitepress_settings;
27
 
28
  $post = (is_integer($post)) ? get_post($post) : $post;
29
  $post_type = $post->post_type;
@@ -37,22 +38,11 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
37
  return trim($permalink, "/");
38
  }
39
 
40
- // 2. Apend the language code as a non-editable prefix
41
- if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
42
- $post_lang_details = apply_filters('wpml_post_language_details', NULL, $post->ID);
43
- $language_code = (!empty($post_lang_details['language_code'])) ? "{$post_lang_details['language_code']}/" : '';
44
-
45
- // Hide language code if "Use directory for default language" option is enabled
46
- $default_language = Permalink_Manager_Helper_Functions::get_language();
47
- if(isset($sitepress_settings['urls']['directory_for_default_language']) && ($sitepress_settings['urls']['directory_for_default_language'] == 0) && ($default_language == $post_lang_details['language_code'])) {
48
- $language_code = "";
49
- }
50
- } else {
51
- $language_code = "";
52
- }
53
 
54
  // 3. Filter only the posts with custom permalink assigned
55
- if(isset($permalink_manager_uris[$post->ID])) { $permalink = get_option('home') . "/{$language_code}{$permalink_manager_uris[$post->ID]}"; }
56
 
57
  // 4. Additional filter
58
  $permalink = apply_filters('permalink_manager_filter_final_post_permalink', user_trailingslashit($permalink), $post);
@@ -91,7 +81,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
91
  * Get the default (not overwritten by the user) or native URI (unfiltered)
92
  */
93
  public static function get_default_post_uri($post, $native_uri = false) {
94
- global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $sitepress_settings;
95
 
96
  // Load all bases & post
97
  $post = is_object($post) ? $post : get_post($post);
@@ -123,8 +113,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
123
  }
124
 
125
  // 2. Fix for hierarchical CPT (start)
126
- $full_slug = ($native_uri == false) ? apply_filters('permalink_manager_filter_default_post_slug', get_page_uri($post), $post, $post_name) : get_page_uri($post);
127
  $full_slug = (empty($full_slug)) ? $post_name : $full_slug;
 
128
  $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
129
 
130
  // 3A. Do the replacement (post tag is removed now to enable support for hierarchical CPT)
@@ -155,7 +146,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
155
  $default_uri = str_replace('//', '/', $default_uri);
156
  $default_uri = trim($default_uri, "/");
157
 
158
- return $default_uri;
159
  }
160
 
161
  /**
@@ -186,52 +177,74 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
186
  $updated_array = array();
187
  $alert_type = $alert_content = $errors = '';
188
 
189
- // Prepare default variables from $_POST object
190
  $old_string = str_replace($home_url, '', esc_sql($_POST['old_string']));
191
  $new_string = str_replace($home_url, '', esc_sql($_POST['new_string']));
192
- $mode = isset($_POST['mode']) ? $_POST['mode'] : array('both');
193
  $post_types_array = ($_POST['post_types']);
194
  $post_statuses_array = ($_POST['post_statuses']);
195
  $post_types = implode("', '", $post_types_array);
196
  $post_statuses = implode("', '", $post_statuses_array);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- // Save the rows before they are updated to an array
199
- $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
200
 
201
  // Now if the array is not empty use IDs from each subarray as a key
202
  if($posts_to_update && empty($errors)) {
203
  foreach ($posts_to_update as $row) {
204
-
205
- // Prepare variables
206
- $old_post_name = $row['post_name'];
207
  $native_uri = self::get_default_post_uri($row['ID'], true);
208
  $default_uri = self::get_default_post_uri($row['ID']);
 
209
  $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $default_uri;
210
- $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
211
 
212
  // Do replacement on slugs (non-REGEX)
213
  if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
214
  // Use $_POST['old_string'] directly here & fix double slashes problem
215
- $pattern = "~" . stripslashes(trim($_POST['old_string'], "/")) . "~";
216
 
217
- $new_post_name = (in_array($mode, array('post_names'))) ? preg_replace($pattern, $new_string, $old_post_name) : $old_post_name;
218
- $new_uri = preg_replace($pattern, $new_string, $old_uri);
219
- }
220
- else {
221
- $new_post_name = (in_array($mode, array('post_names'))) ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
222
- $new_uri = str_replace($old_string, $new_string, $old_uri);
223
  }
224
 
225
  //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
226
 
227
  // Check if native slug should be changed
228
- if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
229
  self::update_slug_by_id($new_post_name, $row['ID']);
230
  }
231
 
232
  if(($old_uri != $new_uri) || ($old_post_name != $new_post_name) && !(empty($new_uri))) {
233
  $permalink_manager_uris[$row['ID']] = $new_uri;
234
- $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
235
  $updated_slugs_count++;
236
  }
237
 
@@ -261,7 +274,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
261
  // Check if post types & statuses are not empty
262
  if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
263
 
264
- // Setup needed variables
265
  $updated_slugs_count = 0;
266
  $updated_array = array();
267
  $alert_type = $alert_content = $errors = '';
@@ -270,39 +283,63 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
270
  $post_statuses_array = ($_POST['post_statuses']) ? $_POST['post_statuses'] : '';
271
  $post_types = implode("', '", $post_types_array);
272
  $post_statuses = implode("', '", $post_statuses_array);
273
- $mode = isset($_POST['mode']) ? $_POST['mode'] : 'both';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
- // Save the rows before they are updated to an array
276
- $posts_to_update = $wpdb->get_results("SELECT post_title, post_name, post_type, ID FROM {$wpdb->posts} WHERE post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')", ARRAY_A);
277
 
278
  // Now if the array is not empty use IDs from each subarray as a key
279
  if($posts_to_update && empty($errors)) {
280
  foreach ($posts_to_update as $row) {
281
- $updated = 0;
 
282
 
283
- // Prepare variables
284
- $old_post_name = $row['post_name'];
285
  $native_uri = self::get_default_post_uri($row['ID'], true);
286
  $default_uri = self::get_default_post_uri($row['ID']);
 
287
  $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
288
- $old_slug = (strpos($old_uri, '/') !== false) ? substr($old_uri, strrpos($old_uri, '/') + 1) : $old_uri;
289
  $correct_slug = sanitize_title($row['post_title']);
290
 
291
  // Process URI & slug
292
  $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
293
- $new_post_name = (in_array($mode, array('post_names'))) ? $new_slug : $old_post_name; // Post name is changed only in first mode
294
- $new_uri = (in_array($mode, array('both'))) ? $default_uri : str_replace($old_slug, $new_slug, $old_uri);
295
 
296
  //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
297
 
298
  // Check if native slug should be changed
299
- if(in_array($mode, array('post_names')) && ($old_post_name != $new_post_name)) {
300
  self::update_slug_by_id($new_post_name, $row['ID']);
301
  }
302
 
303
  if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
304
  $permalink_manager_uris[$row['ID']] = $new_uri;
305
- $updated_array[] = array('post_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
306
  $updated_slugs_count++;
307
  }
308
 
@@ -341,6 +378,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
341
 
342
  if (!empty($new_uris)) {
343
  foreach($new_uris as $id => $new_uri) {
 
 
 
344
  // Prepare variables
345
  $this_post = get_post($id);
346
  $updated = '';
@@ -360,7 +400,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
360
 
361
  if($new_uri != $old_uri) {
362
  $old_uris[$id] = $new_uri;
363
- $updated_array[] = array('post_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
364
  $updated_slugs_count++;
365
  }
366
 
@@ -387,69 +427,79 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
387
  * Allow to edit URIs from "Edit Post" admin pages
388
  */
389
  function edit_uri_box($html, $id, $new_title, $new_slug, $post) {
390
- global $permalink_manager_uris, $sitepress_settings;
391
 
392
  // Detect auto drafts
393
  $autosave = (!empty($new_title) && empty($new_slug)) ? true : false;
394
 
395
- // Get the post object
396
- $post = get_post($id);
397
-
398
  // Do not do anything if new slug is empty or page is front-page
399
- if( get_option('page_on_front') == $id) { return $html; }
400
 
401
  $html = preg_replace("/(<strong>(.*)<\/strong>)(.*)/is", "$1 ", $html);
402
  $default_uri = self::get_default_post_uri($id);
 
403
 
404
  // Make sure that home URL ends with slash
405
  $home_url = trim(get_option('home'), "/") . "/";
406
 
407
- // WPML - apend the language code as a non-editable prefix
408
- if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
409
- $post_lang_details = apply_filters('wpml_post_language_details', NULL, $id);
410
- $language_code = (!empty($post_lang_details['language_code'])) ? $post_lang_details['language_code'] : '';
411
-
412
- // Last instance - use language paramater from &_GET array
413
- $language_code = (empty($language_code) && !empty($_GET['lang'])) ? $_GET['lang'] : $language_code;
414
-
415
- // Hide language code if "Use directory for default language" option is enabled
416
- $default_language = Permalink_Manager_Helper_Functions::get_language();
417
- if(isset($sitepress_settings['urls']['directory_for_default_language']) && ($sitepress_settings['urls']['directory_for_default_language'] == 0) && ($default_language == $language_code)) {
418
- $language_code = '';
419
- }
420
- } else {
421
- $language_code = "";
422
- }
423
-
424
- // Append slash to the end of language code if it is not empty
425
- $language_code .= ($language_code) ? "/" : "";
426
 
427
  // Do not change anything if post is not saved yet (display sample permalink instead)
428
  if($autosave || empty($post->post_status)) {
429
- $sample_permalink = $home_url . str_replace("//", "/", trim("{$language_code}{$default_uri}", "/"));
430
-
431
- $html .= "<span><a href=\"{$sample_permalink}\">{$sample_permalink}</a></span>";
432
  } else {
433
- $uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $default_uri;
434
- $html .= "{$home_url}{$language_code} <span id=\"editable-post-name\"><input type='text' value='{$uri}' name='custom_uri'/></span>";
435
  }
436
 
437
- return $html;
438
- }
439
-
440
- function display_post_link($post) {
441
- global $permalink_manager_uris;
442
-
443
- // Do not display the link on drafts & scheduled posts
444
- if(in_array($post->post_status, array('draft', 'pending', 'auto-draft', 'future'))) { return; }
445
-
446
- $button_text = __('Go to the post', 'permalink-manager');
447
- $permalink = get_permalink($post->ID);
448
-
449
- $html = "<div class=\"misc-pub-section permalink-manager-link\" id=\"permalink-manager\">";
450
- $html .= "<span class=\"image yoast-logo svg bad\"></span><span class=\"score-text\">" . PERMALINK_MANAGER_PLUGIN_NAME . ": <a href=\"{$permalink}\" target=\"_blank\">{$button_text}</a></div>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
 
452
- echo $html;
453
  }
454
 
455
  /**
@@ -464,14 +514,19 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
464
  $post = get_post($post_id);
465
 
466
  // Ignore auto-drafts & removed posts
467
- if(in_array($post->post_status, array('auto-draft', 'trash')) || empty($post->post_name) || (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)) { return; }
 
 
 
 
 
468
 
469
  $default_uri = self::get_default_post_uri($post_id);
470
  $native_uri = self::get_default_post_uri($post_id, true);
471
  $old_uri = (isset($permalink_manager_uris[$post->ID])) ? $permalink_manager_uris[$post->ID] : $native_uri;
472
 
473
- // Use default URI if URI is cleared by user
474
- $new_uri = (!empty($_POST['custom_uri'])) ? trim($_POST['custom_uri'], "/") : $default_uri;
475
 
476
  // Do not store default values
477
  if(isset($permalink_manager_uris[$post->ID]) && ($new_uri == $native_uri)) {
@@ -482,11 +537,11 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
482
  $permalink_manager_uris[$post->ID] = $new_uri;
483
  }
484
 
485
- if(!empty($permalink_manager_options['miscellaneous']['debug_mode'])) {
486
- $debug_data = "<pre>" . print_r($post, true) . "</pre><br />";
487
- $debug_data .= "Update: " . print_r($update, true);
488
- $debug_data .= "<br/>Native URI: <em>{$native_uri}</em><br/>Defualt URI: <em>{$default_uri}</em><br/>New URI: <em>{$new_uri}</em><br/>";
489
- wp_die($debug_data);
490
  }
491
 
492
  update_option('permalink-manager-uris', $permalink_manager_uris);
@@ -506,6 +561,22 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
506
  update_option('permalink-manager-uris', $permalink_manager_uris);
507
  }
508
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  }
510
 
511
  ?>
7
 
8
  public function __construct() {
9
  add_filter( 'get_sample_permalink_html', array($this, 'edit_uri_box'), 999, 5 );
 
10
 
11
  add_filter( '_get_page_link', array($this, 'custom_post_permalinks'), 999, 2);
12
  add_filter( 'page_link', array($this, 'custom_post_permalinks'), 999, 2);
14
  add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 999, 2);
15
 
16
  add_filter( 'permalink-manager-uris', array($this, 'exclude_homepage'), 999, 2);
17
+ add_action( 'save_post', array($this, 'update_post_uri'), 999, 3 );
18
  add_action( 'wp_trash_post', array($this, 'remove_post_uri'), 10, 3 );
19
+
20
+ add_filter( 'permalink_manager_filter_default_post_slug', array($this, 'force_custom_slugs'), 5, 3 );
21
  }
22
 
23
  /**
24
  * Change permalinks for posts, pages & custom post types
25
  */
26
  function custom_post_permalinks($permalink, $post) {
27
+ global $wp_rewrite, $permalink_manager_uris;
28
 
29
  $post = (is_integer($post)) ? get_post($post) : $post;
30
  $post_type = $post->post_type;
38
  return trim($permalink, "/");
39
  }
40
 
41
+ // 2. Apend the language code as a non-editable prefix (can be used also for another prefixes)
42
+ $prefix = apply_filters('permalink-manager-post-permalink-prefix', '', $post);
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  // 3. Filter only the posts with custom permalink assigned
45
+ if(isset($permalink_manager_uris[$post->ID])) { $permalink = get_option('home') . "/{$prefix}{$permalink_manager_uris[$post->ID]}"; }
46
 
47
  // 4. Additional filter
48
  $permalink = apply_filters('permalink_manager_filter_final_post_permalink', user_trailingslashit($permalink), $post);
81
  * Get the default (not overwritten by the user) or native URI (unfiltered)
82
  */
83
  public static function get_default_post_uri($post, $native_uri = false) {
84
+ global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs;
85
 
86
  // Load all bases & post
87
  $post = is_object($post) ? $post : get_post($post);
113
  }
114
 
115
  // 2. Fix for hierarchical CPT (start)
116
+ $full_slug = get_page_uri($post);
117
  $full_slug = (empty($full_slug)) ? $post_name : $full_slug;
118
+ $full_slug = ($native_uri == false) ? apply_filters('permalink_manager_filter_default_post_slug', $full_slug, $post, $post_name) : $full_slug;
119
  $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
120
 
121
  // 3A. Do the replacement (post tag is removed now to enable support for hierarchical CPT)
146
  $default_uri = str_replace('//', '/', $default_uri);
147
  $default_uri = trim($default_uri, "/");
148
 
149
+ return apply_filters('permalink_manager_filter_default_post_uri', $default_uri, $post->post_name, $post, $post_name, $native_uri);
150
  }
151
 
152
  /**
177
  $updated_array = array();
178
  $alert_type = $alert_content = $errors = '';
179
 
180
+ // Process the variables from $_POST object
181
  $old_string = str_replace($home_url, '', esc_sql($_POST['old_string']));
182
  $new_string = str_replace($home_url, '', esc_sql($_POST['new_string']));
183
+
184
  $post_types_array = ($_POST['post_types']);
185
  $post_statuses_array = ($_POST['post_statuses']);
186
  $post_types = implode("', '", $post_types_array);
187
  $post_statuses = implode("', '", $post_statuses_array);
188
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : 'custom_uris';
189
+
190
+ // Filter the posts by IDs
191
+ $where = '';
192
+ if(!empty($_POST['ids'])) {
193
+ // Remove whitespaces and prepare array with IDs and/or ranges
194
+ $ids = esc_sql(preg_replace('/\s*/m', '', $_POST['ids']));
195
+ preg_match_all("/([\d]+(?:-?[\d]+)?)/x", $ids, $groups);
196
+
197
+ // Prepare the extra ID filters
198
+ $where .= "AND (";
199
+ foreach($groups[0] as $group) {
200
+ $where .= ($group == reset($groups[0])) ? "" : " OR ";
201
+ // A. Single number
202
+ if(is_numeric($group)) {
203
+ $where .= "(ID = {$group})";
204
+ }
205
+ // B. Range
206
+ else if(substr_count($group, '-')) {
207
+ $range_edges = explode("-", $group);
208
+ $where .= "(ID BETWEEN {$range_edges[0]} AND {$range_edges[1]})";
209
+ }
210
+ }
211
+ $where .= ")";
212
+ }
213
 
214
+ // Get the rows before they are altered
215
+ $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}') {$where}", ARRAY_A);
216
 
217
  // Now if the array is not empty use IDs from each subarray as a key
218
  if($posts_to_update && empty($errors)) {
219
  foreach ($posts_to_update as $row) {
220
+ // Get default & native URL
 
 
221
  $native_uri = self::get_default_post_uri($row['ID'], true);
222
  $default_uri = self::get_default_post_uri($row['ID']);
223
+ $old_post_name = $row['post_name'];
224
  $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $default_uri;
 
225
 
226
  // Do replacement on slugs (non-REGEX)
227
  if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
228
  // Use $_POST['old_string'] directly here & fix double slashes problem
229
+ $pattern = "~" . stripslashes(trim(sanitize_text_field($_POST['old_string']), "/")) . "~";
230
 
231
+ $new_post_name = ($mode == 'slugs') ? preg_replace($pattern, $new_string, $old_post_name) : $old_post_name;
232
+ $new_uri = ($mode != 'slugs') ? preg_replace($pattern, $new_string, $old_uri) : $old_uri;
233
+ } else {
234
+ $new_post_name = ($mode == 'slugs') ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
235
+ $new_uri = ($mode != 'slugs') ? str_replace($old_string, $new_string, $old_uri) : $old_uri;
 
236
  }
237
 
238
  //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
239
 
240
  // Check if native slug should be changed
241
+ if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
242
  self::update_slug_by_id($new_post_name, $row['ID']);
243
  }
244
 
245
  if(($old_uri != $new_uri) || ($old_post_name != $new_post_name) && !(empty($new_uri))) {
246
  $permalink_manager_uris[$row['ID']] = $new_uri;
247
+ $updated_array[] = array('item_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
248
  $updated_slugs_count++;
249
  }
250
 
274
  // Check if post types & statuses are not empty
275
  if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
276
 
277
+ // Process the variables from $_POST object
278
  $updated_slugs_count = 0;
279
  $updated_array = array();
280
  $alert_type = $alert_content = $errors = '';
283
  $post_statuses_array = ($_POST['post_statuses']) ? $_POST['post_statuses'] : '';
284
  $post_types = implode("', '", $post_types_array);
285
  $post_statuses = implode("', '", $post_statuses_array);
286
+ $mode = isset($_POST['mode']) ? $_POST['mode'] : 'custom_uris';
287
+
288
+ // Filter the posts by IDs
289
+ $where = '';
290
+ if(!empty($_POST['ids'])) {
291
+ // Remove whitespaces and prepare array with IDs and/or ranges
292
+ $ids = esc_sql(preg_replace('/\s*/m', '', $_POST['ids']));
293
+ preg_match_all("/([\d]+(?:-?[\d]+)?)/x", $ids, $groups);
294
+
295
+ // Prepare the extra ID filters
296
+ $where .= "AND (";
297
+ foreach($groups[0] as $group) {
298
+ $where .= ($group == reset($groups[0])) ? "" : " OR ";
299
+ // A. Single number
300
+ if(is_numeric($group)) {
301
+ $where .= "(ID = {$group})";
302
+ }
303
+ // B. Range
304
+ else if(substr_count($group, '-')) {
305
+ $range_edges = explode("-", $group);
306
+ $where .= "(ID BETWEEN {$range_edges[0]} AND {$range_edges[1]})";
307
+ }
308
+ }
309
+ $where .= ")";
310
+ }
311
 
312
+ // Get the rows before they are altered
313
+ $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}') {$where}", ARRAY_A);
314
 
315
  // Now if the array is not empty use IDs from each subarray as a key
316
  if($posts_to_update && empty($errors)) {
317
  foreach ($posts_to_update as $row) {
318
+ // Prevent server timeout
319
+ set_time_limit(0);
320
 
321
+ // Get default & native URL
 
322
  $native_uri = self::get_default_post_uri($row['ID'], true);
323
  $default_uri = self::get_default_post_uri($row['ID']);
324
+ $old_post_name = $row['post_name'];
325
  $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
 
326
  $correct_slug = sanitize_title($row['post_title']);
327
 
328
  // Process URI & slug
329
  $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
330
+ $new_post_name = ($mode == 'slugs') ? $new_slug : $old_post_name; // Post name is changed only in first mode
331
+ $new_uri = ($mode == 'slugs') ? $old_uri : $default_uri;
332
 
333
  //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
334
 
335
  // Check if native slug should be changed
336
+ if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
337
  self::update_slug_by_id($new_post_name, $row['ID']);
338
  }
339
 
340
  if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
341
  $permalink_manager_uris[$row['ID']] = $new_uri;
342
+ $updated_array[] = array('item_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
343
  $updated_slugs_count++;
344
  }
345
 
378
 
379
  if (!empty($new_uris)) {
380
  foreach($new_uris as $id => $new_uri) {
381
+ // Prevent server timeout
382
+ set_time_limit(0);
383
+
384
  // Prepare variables
385
  $this_post = get_post($id);
386
  $updated = '';
400
 
401
  if($new_uri != $old_uri) {
402
  $old_uris[$id] = $new_uri;
403
+ $updated_array[] = array('item_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
404
  $updated_slugs_count++;
405
  }
406
 
427
  * Allow to edit URIs from "Edit Post" admin pages
428
  */
429
  function edit_uri_box($html, $id, $new_title, $new_slug, $post) {
430
+ global $permalink_manager_uris, $permalink_manager_options;
431
 
432
  // Detect auto drafts
433
  $autosave = (!empty($new_title) && empty($new_slug)) ? true : false;
434
 
 
 
 
435
  // Do not do anything if new slug is empty or page is front-page
436
+ if(get_option('page_on_front') == $id) { return $html; }
437
 
438
  $html = preg_replace("/(<strong>(.*)<\/strong>)(.*)/is", "$1 ", $html);
439
  $default_uri = self::get_default_post_uri($id);
440
+ $native_uri = self::get_default_post_uri($id, true);
441
 
442
  // Make sure that home URL ends with slash
443
  $home_url = trim(get_option('home'), "/") . "/";
444
 
445
+ $prefix = apply_filters('permalink-manager-post-permalink-prefix', '', $post, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
 
447
  // Do not change anything if post is not saved yet (display sample permalink instead)
448
  if($autosave || empty($post->post_status)) {
449
+ $sample_permalink = $default_uri;
 
 
450
  } else {
451
+ //$uri = $sample_permalink = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $default_uri;
452
+ $uri = $sample_permalink = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri;
453
  }
454
 
455
+ // Prepare the sample & default permalink
456
+ $sample_permalink = sprintf("{$home_url}{$prefix}<span class=\"editable\">%s</span>", str_replace("//", "/", trim($sample_permalink, "/")));
457
+
458
+ // Append new HTML output
459
+ $html .= sprintf("<span class=\"sample-permalink-span\"><a href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
460
+
461
+ if(!empty($uri)) {
462
+ // Auto-update settings
463
+ $auto_update_val = get_post_meta($id, "auto_update_uri", true);
464
+ $auto_update_def_val = $permalink_manager_options["general"]["auto_update_uris"];
465
+ $auto_update_def_label = ($auto_update_def_val) ? __("Yes", "permalink-manager") : __("No", "permalink-manager");
466
+ $auto_update_choices = array(
467
+ 0 => array("label" => sprintf(__("Use global settings [%s]", "permalink-manager"), $auto_update_def_label), "atts" => "data-auto-update=\"{$auto_update_def_val}\""),
468
+ -1 => array("label" => __("No", "permalink-manager"), "atts" => "data-auto-update=\"0\""),
469
+ 1 => array("label" => __("Yes", "permalink-manager"), "atts" => "data-auto-update=\"1\"")
470
+ );
471
+
472
+ // Add the "edit buttons"
473
+ $html .= sprintf("<span><button type=\"button\" class=\"button button-small hide-if-no-js\" id=\"permalink-manager-toggle\">%s</button></span>", __("Permalink Manager", "permalink-manager"));
474
+ $html .= "<div id=\"permalink-manager\" class=\"postbox permalink-manager-edit-uri-box\" style=\"display: none;\">";
475
+
476
+ // The heading
477
+ $html .= "<a class=\"close-button\"><span class=\"screen-reader-text\">" . __("Close: ", "permalink-manager") . __("Permalink Manager", "permalink-manager") . "</span><span class=\"close-icon\" aria-hidden=\"false\"></span></a>";
478
+ $html .= sprintf("<h2><span>%s</span></h2>", __("Permalink Manager", "permalink-manager"));
479
+
480
+ // The fields
481
+ $html .= "<div class=\"inside\">";
482
+ $html .= sprintf("<p><label for=\"custom_uri\" class=\"strong\">%s %s</label><span>%s</span></p>",
483
+ __("Current URI", "permalink-manager"),
484
+ Permalink_Manager_Admin_Functions::help_tooltip(__("The custom URI can be edited only if 'Auto-update the URI' feature is not enabled.", "permalink-manager")),
485
+ Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("extra_atts" => "data-default-uri=\"{$default_uri}\"", "input_class" => "widefat custom_uri", "value" => $uri))
486
+ );
487
+ $html .= sprintf("<p><label for=\"auto_auri\" class=\"strong\">%s %s</label><span>%s</span></p>",
488
+ __("Auto-update the URI", "permalink-manager"),
489
+ Permalink_Manager_Admin_Functions::help_tooltip(__("If enabled, the 'Current URI' field will be automatically changed to 'Default URI' (displayed below) after the post is saved or updated.", "permalink-manager")),
490
+ Permalink_Manager_Admin_Functions::generate_option_field("auto_update_uri", array("type" => "select", "input_class" => "widefat auto_update", "value" => $auto_update_val, "choices" => $auto_update_choices))
491
+ );
492
+ $html .= sprintf(
493
+ "<p class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" id=\"restore-default-uri\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></p>",
494
+ __("Default URI", "permalink-manager"), esc_html($default_uri),
495
+ __("Restore to Default URI", "permalink-manager")
496
+ );
497
+ $html .= "</div>";
498
+
499
+ $html .= "</div>";
500
+ }
501
 
502
+ return $html;
503
  }
504
 
505
  /**
514
  $post = get_post($post_id);
515
 
516
  // Ignore auto-drafts & removed posts
517
+ //if(in_array($post->post_status, array('auto-draft', 'trash')) || empty($post->post_name) || (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)) { return; }
518
+ if(in_array($post->post_status, array('auto-draft', 'trash')) || (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)) { return; }
519
+
520
+ // Get auto-update URI setting (if empty use global setting)
521
+ $auto_update_uri_current = (!empty($_POST["auto_update_uri"])) ? intval($_POST["auto_update_uri"]) : 0;
522
+ $auto_update_uri = (!empty($_POST["auto_update_uri"])) ? $auto_update_uri_current : $permalink_manager_options["general"]["auto_update_uris"];
523
 
524
  $default_uri = self::get_default_post_uri($post_id);
525
  $native_uri = self::get_default_post_uri($post_id, true);
526
  $old_uri = (isset($permalink_manager_uris[$post->ID])) ? $permalink_manager_uris[$post->ID] : $native_uri;
527
 
528
+ // Use default URI if URI is cleared by user OR URI should be automatically updated
529
+ $new_uri = (empty($_POST['custom_uri']) || $auto_update_uri == 1) ? $default_uri : trim($_POST['custom_uri'], "/");
530
 
531
  // Do not store default values
532
  if(isset($permalink_manager_uris[$post->ID]) && ($new_uri == $native_uri)) {
537
  $permalink_manager_uris[$post->ID] = $new_uri;
538
  }
539
 
540
+ // Save or remove "Auto-update URI" settings
541
+ if(!empty($auto_update_uri_current)) {
542
+ update_post_meta($post_id, "auto_update_uri", $auto_update_uri_current);
543
+ } else {
544
+ delete_post_meta($post_id, "auto_update_uri");
545
  }
546
 
547
  update_option('permalink-manager-uris', $permalink_manager_uris);
561
  update_option('permalink-manager-uris', $permalink_manager_uris);
562
  }
563
 
564
+ /**
565
+ * Force custom slugs
566
+ */
567
+ public function force_custom_slugs($slug, $object, $name) {
568
+ global $permalink_manager_options;
569
+
570
+ if(!empty($permalink_manager_options['general']['force_custom_slugs'])) {
571
+ $old_slug = basename($slug);
572
+ $new_slug = sanitize_title($object->post_title);
573
+
574
+ $slug = ($old_slug != $new_slug) ? str_replace($old_slug, $new_slug, $slug) : $slug;
575
+ }
576
+
577
+ return $slug;
578
+ }
579
+
580
  }
581
 
582
  ?>
includes/views/{permalink-manager-advanced.php → permalink-manager-debug.php} RENAMED
@@ -3,16 +3,16 @@
3
  /**
4
  * Display the page where the slugs could be regenerated or replaced
5
  */
6
- class Permalink_Manager_Advanced extends Permalink_Manager_Class {
7
 
8
  public function __construct() {
9
- add_filter( 'permalink-manager-sections', array($this, 'add_advanced_section'), 1 );
10
  }
11
 
12
- public function add_advanced_section($admin_sections) {
13
  $admin_sections['debug'] = array(
14
  'name' => __('Debug', 'permalink-manager'),
15
- 'function' => array('class' => 'Permalink_Manager_Advanced', 'method' => 'output')
16
  );
17
 
18
  return $admin_sections;
@@ -21,15 +21,12 @@ class Permalink_Manager_Advanced extends Permalink_Manager_Class {
21
  public function output() {
22
  global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_filter;
23
 
24
- // Append PHP & plugin version
25
- $permalink_manager_info = array_merge($permalink_manager_options, array('php_version' => phpversion(), 'plugin_version' => PERMALINK_MANAGER_VERSION));
26
-
27
  // Get permalink hooks
28
  foreach(array('_get_page_link', 'post_link', 'page_link', 'post_type_link') as $hook) {
29
- $permalink_hooks[$hook] = $wp_filter[$hook];
30
  }
31
 
32
- $sections_and_fields = apply_filters('permalink-manager-advanced-fields', array(
33
  'debug-data' => array(
34
  'section_name' => __('Debug data', 'permalink-manager'),
35
  'fields' => array(
@@ -38,28 +35,28 @@ class Permalink_Manager_Advanced extends Permalink_Manager_Class {
38
  'description' => __('List of the URIs generated by this plugin.', 'permalink-manager'),
39
  'label' => __('Array with URIs', 'permalink-manager'),
40
  'input_class' => 'short-textarea widefat',
41
- 'value' => ($permalink_manager_uris) ? json_encode($permalink_manager_uris, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) : ''
42
  ),
43
  'permastructs' => array(
44
  'type' => 'textarea',
45
  'description' => __('List of the permastructures.', 'permalink-manager'),
46
  'label' => __('Array with permastructures', 'permalink-manager'),
47
  'input_class' => 'short-textarea widefat',
48
- 'value' => ($permalink_manager_permastructs) ? json_encode($permalink_manager_permastructs, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) : ''
49
  ),
50
  'settings' => array(
51
  'type' => 'textarea',
52
- 'description' => __('Plugin data.', 'permalink-manager'),
53
- 'label' => __('Array with settings used in this plugin & some additional information.', 'permalink-manager'),
54
  'input_class' => 'short-textarea widefat',
55
- 'value' => json_encode($permalink_manager_info, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
56
  ),
57
  'hooks' => array(
58
  'type' => 'textarea',
59
  'description' => __('Permalink hooks.', 'permalink-manager'),
60
  'label' => __('Array with list of permalink hooks used on this website.', 'permalink-manager'),
61
  'input_class' => 'short-textarea widefat',
62
- 'value' => json_encode($permalink_hooks, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
63
  )
64
  )
65
  )
3
  /**
4
  * Display the page where the slugs could be regenerated or replaced
5
  */
6
+ class Permalink_Manager_Debug extends Permalink_Manager_Class {
7
 
8
  public function __construct() {
9
+ add_filter( 'permalink-manager-sections', array($this, 'add_debug_section'), 1 );
10
  }
11
 
12
+ public function add_debug_section($admin_sections) {
13
  $admin_sections['debug'] = array(
14
  'name' => __('Debug', 'permalink-manager'),
15
+ 'function' => array('class' => 'Permalink_Manager_Debug', 'method' => 'output')
16
  );
17
 
18
  return $admin_sections;
21
  public function output() {
22
  global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_filter;
23
 
 
 
 
24
  // Get permalink hooks
25
  foreach(array('_get_page_link', 'post_link', 'page_link', 'post_type_link') as $hook) {
26
+ $permalink_hooks[$hook] = json_encode($wp_filter[$hook]);
27
  }
28
 
29
+ $sections_and_fields = apply_filters('permalink-manager-debug-fields', array(
30
  'debug-data' => array(
31
  'section_name' => __('Debug data', 'permalink-manager'),
32
  'fields' => array(
35
  'description' => __('List of the URIs generated by this plugin.', 'permalink-manager'),
36
  'label' => __('Array with URIs', 'permalink-manager'),
37
  'input_class' => 'short-textarea widefat',
38
+ 'value' => ($permalink_manager_uris) ? print_r($permalink_manager_uris, true) : ''
39
  ),
40
  'permastructs' => array(
41
  'type' => 'textarea',
42
  'description' => __('List of the permastructures.', 'permalink-manager'),
43
  'label' => __('Array with permastructures', 'permalink-manager'),
44
  'input_class' => 'short-textarea widefat',
45
+ 'value' => ($permalink_manager_permastructs) ? print_r($permalink_manager_permastructs, true) : ''
46
  ),
47
  'settings' => array(
48
  'type' => 'textarea',
49
+ 'description' => __('Currently used plugin settings.', 'permalink-manager'),
50
+ 'label' => __('Array with settings used in this plugin.', 'permalink-manager'),
51
  'input_class' => 'short-textarea widefat',
52
+ 'value' => print_r($permalink_manager_options, true)
53
  ),
54
  'hooks' => array(
55
  'type' => 'textarea',
56
  'description' => __('Permalink hooks.', 'permalink-manager'),
57
  'label' => __('Array with list of permalink hooks used on this website.', 'permalink-manager'),
58
  'input_class' => 'short-textarea widefat',
59
+ 'value' => print_r($permalink_hooks, true)
60
  )
61
  )
62
  )
includes/views/permalink-manager-settings.php CHANGED
@@ -7,7 +7,6 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
7
 
8
  public function __construct() {
9
  add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
10
- add_filter( 'permalink-manager-options', array($this, 'default_settings'), 9 );
11
  }
12
 
13
  public function add_admin_section($admin_sections) {
@@ -19,36 +18,6 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
19
  return $admin_sections;
20
  }
21
 
22
- /**
23
- * Set the initial/default settings
24
- */
25
- public function default_settings($settings) {
26
- $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
27
- $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
28
-
29
- $default_settings = apply_filters('permalink-manager-default-options', array(
30
- 'screen-options' => array(
31
- 'per_page' => 20,
32
- 'post_statuses' => array('publish'),
33
- 'post_types' => $all_post_types,
34
- 'taxonomies' => $all_taxonomies
35
- ),
36
- 'miscellaneous' => array(
37
- 'yoast_primary_term' => 1,
38
- 'redirect' => "302",
39
- 'canonical_redirect' => 1,
40
- )
41
- ));
42
-
43
- // Apply the default settings (if empty values) in all settings sections
44
- $final_settings = array();
45
- foreach($default_settings as $section => $fields) {
46
- $final_settings[$section] = (isset($settings[$section])) ? array_replace($fields, $settings[$section]) : $fields;
47
- }
48
-
49
- return $final_settings;
50
- }
51
-
52
  /**
53
  * Get the array with settings and render the HTML output
54
  */
@@ -56,31 +25,24 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
56
  // Get all registered post types array & statuses
57
  $all_post_statuses_array = get_post_statuses();
58
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
 
59
 
60
  $sections_and_fields = apply_filters('permalink-manager-settings-fields', array(
61
- 'screen-options' => array(
62
- 'section_name' => __('Display settings', 'permalink-manager'),
63
- 'description' => __('Adjust the data displayed in "Permalink Editor" section.', 'permalink-manager'),
64
  'container' => 'row',
65
  'fields' => array(
66
- 'per_page' => array(
67
- 'type' => 'number',
68
- 'label' => __('Per page', 'permalink-manager'),
69
- 'input_class' => 'settings-select'
70
- ),
71
- 'post_statuses' => array(
72
- 'type' => 'checkbox',
73
- 'label' => __('Post statuses', 'permalink-manager'),
74
- 'choices' => $all_post_statuses_array,
75
- 'select_all' => '',
76
- 'unselect_all' => '',
77
  ),
78
- 'post_types' => array(
79
- 'type' => 'checkbox',
80
- 'label' => __('Post types', 'permalink-manager'),
81
- 'choices' => $all_post_types,
82
- 'select_all' => '',
83
- 'unselect_all' => '',
84
  )
85
  )
86
  ),
@@ -89,29 +51,23 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
89
  'container' => 'row',
90
  'fields' => array(
91
  'yoast_primary_term' => array(
92
- 'type' => 'select',
93
  'label' => __('Primay term/category support', 'permalink-manager'),
94
- 'input_class' => 'settings-select',
95
- 'choices' => array(1 => __('Enable', 'permalink-manager'), 0 => __('Disable', 'permalink-manager')),
96
  'description' => __('Used to generate default permalinks in pages, posts & custom post types. Works only when "Yoast SEO" plugin is enabled.', 'permalink-manager')
97
  ),
 
 
 
 
 
 
98
  'redirect' => array(
99
  'type' => 'select',
100
  'label' => __('Redirect', 'permalink-manager'),
101
  'input_class' => 'settings-select',
102
  'choices' => array(0 => __('Disable', 'permalink-manager'), "301" => __('Enable "301 redirect"', 'permalink-manager'), "302" => __('Enable "302 redirect"', 'permalink-manager')),
103
  'description' => __('If enabled - the visitors will be redirected from native permalinks to your custom permalinks. Please note that the redirects will work correctly only if native slug "post name" will not be changed.', 'permalink-manager')
104
- ),
105
- 'canonical_redirect' => array(
106
- 'type' => 'select',
107
- 'label' => __('Canonical redirect', 'permalink-manager'),
108
- 'input_class' => 'settings-select',
109
- 'choices' => array(0 => __('Disable', 'permalink-manager'), 1 => __('Enable', 'permalink-manager')),
110
- 'description' => __('This function allows Wordpress to correct the URLs used by the visitors.', 'permalink-manager')
111
- ),
112
- 'debug_mode' => array(
113
- 'type' => 'single_checkbox',
114
- 'label' => __('Debug mode', 'permalink-manager')
115
  )
116
  )
117
  )
7
 
8
  public function __construct() {
9
  add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
 
10
  }
11
 
12
  public function add_admin_section($admin_sections) {
18
  return $admin_sections;
19
  }
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * Get the array with settings and render the HTML output
23
  */
25
  // Get all registered post types array & statuses
26
  $all_post_statuses_array = get_post_statuses();
27
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
28
+ $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
29
 
30
  $sections_and_fields = apply_filters('permalink-manager-settings-fields', array(
31
+ 'general' => array(
32
+ 'section_name' => __('General & Interface', 'permalink-manager'),
 
33
  'container' => 'row',
34
  'fields' => array(
35
+ 'auto_update_uris' => array(
36
+ 'type' => 'single_checkbox',
37
+ 'label' => __('Auto-update URIs', 'permalink-manager'),
38
+ 'input_class' => '',
39
+ 'description' => __('If enabled the custom URIs will be automatically updated every time the post is saved or updated.', 'permalink-manager')
 
 
 
 
 
 
40
  ),
41
+ 'force_custom_slugs' => array(
42
+ 'type' => 'single_checkbox',
43
+ 'label' => __('Force custom slugs', 'permalink-manager'),
44
+ 'input_class' => '',
45
+ 'description' => __('If enabled the native slugs in the defult URIs will be recreated from the post title.<br />This may cause URI duplicates when the post title is used more than once.', 'permalink-manager')
 
46
  )
47
  )
48
  ),
51
  'container' => 'row',
52
  'fields' => array(
53
  'yoast_primary_term' => array(
54
+ 'type' => 'single_checkbox',
55
  'label' => __('Primay term/category support', 'permalink-manager'),
56
+ 'input_class' => '',
 
57
  'description' => __('Used to generate default permalinks in pages, posts & custom post types. Works only when "Yoast SEO" plugin is enabled.', 'permalink-manager')
58
  ),
59
+ 'canonical_redirect' => array(
60
+ 'type' => 'single_checkbox',
61
+ 'label' => __('Canonical redirect', 'permalink-manager'),
62
+ 'input_class' => '',
63
+ 'description' => __('This function allows Wordpress to correct the URLs used by the visitors.', 'permalink-manager')
64
+ ),
65
  'redirect' => array(
66
  'type' => 'select',
67
  'label' => __('Redirect', 'permalink-manager'),
68
  'input_class' => 'settings-select',
69
  'choices' => array(0 => __('Disable', 'permalink-manager'), "301" => __('Enable "301 redirect"', 'permalink-manager'), "302" => __('Enable "302 redirect"', 'permalink-manager')),
70
  'description' => __('If enabled - the visitors will be redirected from native permalinks to your custom permalinks. Please note that the redirects will work correctly only if native slug "post name" will not be changed.', 'permalink-manager')
 
 
 
 
 
 
 
 
 
 
 
71
  )
72
  )
73
  )
includes/views/permalink-manager-tools.php CHANGED
@@ -21,6 +21,10 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
21
  'regenerate_slugs' => array(
22
  'name' => __('Regenerate/Reset', 'permalink-manager'),
23
  'function' => array('class' => 'Permalink_Manager_Tools', 'method' => 'regenerate_slugs_output')
 
 
 
 
24
  )
25
  )
26
  );
@@ -29,38 +33,45 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
29
  }
30
 
31
  public function display_instructions() {
32
- return wpautop(__('<strong>A MySQL backup is highly recommended before using "<em>Custom & native slugs (post names)</em>" mode!</strong>.', 'permalink-manager'));
33
  }
34
 
35
  public function find_and_replace_output() {
36
  // Get all registered post types array & statuses
37
  $all_post_statuses_array = get_post_statuses();
38
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
 
39
 
40
- $fields = array(
41
  'old_string' => array(
42
  'label' => __( 'Find ...', 'permalink-manager' ),
43
  'type' => 'text',
44
  'container' => 'row',
45
- 'container_class' => 'column column-1_2',
46
  'input_class' => 'widefat'
47
  ),
48
  'new_string' => array(
49
  'label' => __( 'Replace with ...', 'permalink-manager' ),
50
  'type' => 'text',
51
  'container' => 'row',
52
- 'container_class' => 'column column-1_2',
53
  'input_class' => 'widefat'
54
  ),
55
  'mode' => array(
56
- 'label' => __( 'Select mode', 'permalink-manager' ),
 
 
 
 
 
 
57
  'type' => 'select',
 
 
58
  'container' => 'row',
59
- 'choices' => array('both' => '<strong>' . __('Full URIs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Custom & native slugs (post names)', 'permalink-manager') . '</strong>'),
60
- 'default' => array('both'),
61
  ),
62
  'post_types' => array(
63
- 'label' => __( 'Filter by post types', 'permalink-manager' ),
64
  'type' => 'checkbox',
65
  'container' => 'row',
66
  'default' => array('post', 'page'),
@@ -68,21 +79,41 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
68
  'select_all' => '',
69
  'unselect_all' => '',
70
  ),
 
 
 
 
 
 
 
 
 
 
 
71
  'post_statuses' => array(
72
- 'label' => __( 'Filter by post statuses', 'permalink-manager' ),
73
  'type' => 'checkbox',
74
  'container' => 'row',
75
  'default' => array('publish'),
76
  'choices' => $all_post_statuses_array,
77
  'select_all' => '',
78
  'unselect_all' => '',
 
 
 
 
 
 
 
 
 
79
  )
80
- );
81
 
82
  $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
83
  $sidebar .= self::display_instructions();
84
 
85
- $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Find and replace', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'find_and_replace'));
86
 
87
  return $output;
88
  }
@@ -91,16 +122,26 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
91
  // Get all registered post types array & statuses
92
  $all_post_statuses_array = get_post_statuses();
93
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
 
94
 
95
- $fields = array(
96
  'mode' => array(
97
- 'label' => __( 'Select mode', 'permalink-manager' ),
98
  'type' => 'select',
99
  'container' => 'row',
100
- 'choices' => array('both' => '<strong>' . __('Full URIs', 'permalink-manager') . '</strong>', 'post_names' => '<strong>' . __('Custom & native slugs (post names)', 'permalink-manager') . '</strong>'),
 
 
 
 
 
 
 
 
 
101
  ),
102
  'post_types' => array(
103
- 'label' => __( 'Filter by post types', 'permalink-manager' ),
104
  'type' => 'checkbox',
105
  'container' => 'row',
106
  'default' => array('post', 'page'),
@@ -108,20 +149,41 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
108
  'select_all' => '',
109
  'unselect_all' => '',
110
  ),
 
 
 
 
 
 
 
 
 
 
 
111
  'post_statuses' => array(
112
- 'label' => __( 'Filter by post statuses', 'permalink-manager' ),
113
  'type' => 'checkbox',
114
  'container' => 'row',
115
  'default' => array('publish'),
116
  'choices' => $all_post_statuses_array,
117
  'select_all' => '',
118
  'unselect_all' => '',
 
 
 
 
 
 
 
 
 
119
  )
120
- );
121
 
122
  $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
123
  $sidebar .= self::display_instructions();
124
- $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Regenerate', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'regenerate'));
 
125
 
126
  return $output;
127
  }
21
  'regenerate_slugs' => array(
22
  'name' => __('Regenerate/Reset', 'permalink-manager'),
23
  'function' => array('class' => 'Permalink_Manager_Tools', 'method' => 'regenerate_slugs_output')
24
+ ),
25
+ 'stop_words' => array(
26
+ 'name' => __('Stop words', 'permalink-manager'),
27
+ 'function' => array('class' => 'Permalink_Manager_Admin_Functions', 'method' => 'pro_text')
28
  )
29
  )
30
  );
33
  }
34
 
35
  public function display_instructions() {
36
+ return wpautop(__('<strong>A MySQL backup is highly recommended before using "<em>Native slugs</em>" mode!</strong>', 'permalink-manager'));
37
  }
38
 
39
  public function find_and_replace_output() {
40
  // Get all registered post types array & statuses
41
  $all_post_statuses_array = get_post_statuses();
42
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
43
+ $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
44
 
45
+ $fields = apply_filters('permalink-manager-tools-fields', array(
46
  'old_string' => array(
47
  'label' => __( 'Find ...', 'permalink-manager' ),
48
  'type' => 'text',
49
  'container' => 'row',
 
50
  'input_class' => 'widefat'
51
  ),
52
  'new_string' => array(
53
  'label' => __( 'Replace with ...', 'permalink-manager' ),
54
  'type' => 'text',
55
  'container' => 'row',
 
56
  'input_class' => 'widefat'
57
  ),
58
  'mode' => array(
59
+ 'label' => __( 'Mode', 'permalink-manager' ),
60
+ 'type' => 'select',
61
+ 'container' => 'row',
62
+ 'choices' => array('custom_uris' => __('Custom URIs', 'permalink-manager'), 'slugs' => __('Native slugs', 'permalink-manager')),
63
+ ),
64
+ 'content_type' => array(
65
+ 'label' => __( 'Select content type', 'permalink-manager' ),
66
  'type' => 'select',
67
+ 'disabled' => true,
68
+ 'pro' => true,
69
  'container' => 'row',
70
+ 'default' => 'post_types',
71
+ 'choices' => array('post_types' => __('Post types', 'permalink-manager'), 'taxonomies' => __('Taxonomies', 'permalink-manager')),
72
  ),
73
  'post_types' => array(
74
+ 'label' => __( 'Select post types', 'permalink-manager' ),
75
  'type' => 'checkbox',
76
  'container' => 'row',
77
  'default' => array('post', 'page'),
79
  'select_all' => '',
80
  'unselect_all' => '',
81
  ),
82
+ 'taxonomies' => array(
83
+ 'label' => __( 'Select taxonomies', 'permalink-manager' ),
84
+ 'type' => 'checkbox',
85
+ 'container' => 'row',
86
+ 'container_class' => 'hidden',
87
+ 'default' => array('category', 'post_tag'),
88
+ 'choices' => $all_taxonomies,
89
+ 'pro' => true,
90
+ 'select_all' => '',
91
+ 'unselect_all' => '',
92
+ ),
93
  'post_statuses' => array(
94
+ 'label' => __( 'Select post statuses', 'permalink-manager' ),
95
  'type' => 'checkbox',
96
  'container' => 'row',
97
  'default' => array('publish'),
98
  'choices' => $all_post_statuses_array,
99
  'select_all' => '',
100
  'unselect_all' => '',
101
+ ),
102
+ 'ids' => array(
103
+ 'label' => __( 'Select IDs', 'permalink-manager' ),
104
+ 'type' => 'text',
105
+ 'container' => 'row',
106
+ //'disabled' => true,
107
+ 'description' => __('To narrow the above filters you can type the post IDs (or ranges) here. Eg. <strong>1-8, 10, 25</strong>.', 'permalink-manager'),
108
+ //'pro' => true,
109
+ 'input_class' => 'widefat'
110
  )
111
+ ), 'find_and_replace');
112
 
113
  $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
114
  $sidebar .= self::display_instructions();
115
 
116
+ $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __('Find and replace', 'permalink-manager'), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'find_and_replace'), true);
117
 
118
  return $output;
119
  }
122
  // Get all registered post types array & statuses
123
  $all_post_statuses_array = get_post_statuses();
124
  $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
125
+ $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
126
 
127
+ $fields = apply_filters('permalink-manager-tools-fields', array(
128
  'mode' => array(
129
+ 'label' => __( 'Mode', 'permalink-manager' ),
130
  'type' => 'select',
131
  'container' => 'row',
132
+ 'choices' => array('custom_uris' => __('Custom URIs', 'permalink-manager'), 'slugs' => __('Native slugs', 'permalink-manager')),
133
+ ),
134
+ 'content_type' => array(
135
+ 'label' => __( 'Select content type', 'permalink-manager' ),
136
+ 'type' => 'select',
137
+ 'disabled' => true,
138
+ 'pro' => true,
139
+ 'container' => 'row',
140
+ 'default' => 'post_types',
141
+ 'choices' => array('post_types' => __('Post types', 'permalink-manager'), 'taxonomies' => __('Taxonomies', 'permalink-manager')),
142
  ),
143
  'post_types' => array(
144
+ 'label' => __( 'Select post types', 'permalink-manager' ),
145
  'type' => 'checkbox',
146
  'container' => 'row',
147
  'default' => array('post', 'page'),
149
  'select_all' => '',
150
  'unselect_all' => '',
151
  ),
152
+ 'taxonomies' => array(
153
+ 'label' => __( 'Select taxonomies', 'permalink-manager' ),
154
+ 'type' => 'checkbox',
155
+ 'container' => 'row',
156
+ 'container_class' => 'hidden',
157
+ 'default' => array('category', 'post_tag'),
158
+ 'choices' => $all_taxonomies,
159
+ 'pro' => true,
160
+ 'select_all' => '',
161
+ 'unselect_all' => '',
162
+ ),
163
  'post_statuses' => array(
164
+ 'label' => __( 'Select post statuses', 'permalink-manager' ),
165
  'type' => 'checkbox',
166
  'container' => 'row',
167
  'default' => array('publish'),
168
  'choices' => $all_post_statuses_array,
169
  'select_all' => '',
170
  'unselect_all' => '',
171
+ ),
172
+ 'ids' => array(
173
+ 'label' => __( 'Select IDs', 'permalink-manager' ),
174
+ 'type' => 'text',
175
+ 'container' => 'row',
176
+ //'disabled' => true,
177
+ 'description' => __('To narrow the above filters you can type the post IDs (or ranges) here. Eg. <strong>1-8, 10, 25</strong>.', 'permalink-manager'),
178
+ //'pro' => true,
179
+ 'input_class' => 'widefat'
180
  )
181
+ ), 'regenerate');
182
 
183
  $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
184
  $sidebar .= self::display_instructions();
185
+
186
+ $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Regenerate', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'regenerate'), true);
187
 
188
  return $output;
189
  }
includes/views/permalink-manager-uri-editor-post.php CHANGED
@@ -5,13 +5,18 @@
5
  */
6
  class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
7
 
 
 
8
  public function __construct() {
9
- global $status, $page;
10
 
11
  parent::__construct(array(
12
  'singular' => 'slug',
13
  'plural' => 'slugs'
14
  ));
 
 
 
15
  }
16
 
17
  /**
@@ -41,21 +46,14 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
41
  * Override the parent columns method. Defines the columns to use in your listing table
42
  */
43
  public function get_columns() {
44
- $columns = array(
45
  //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
46
  'post_title' => __('Post title', 'permalink-manager'),
47
  'post_name' => __('Post name (native slug)', 'permalink-manager'),
48
  //'post_date_gmt' => __('Date', 'permalink-manager'),
49
  'uri' => __('Full URI & Permalink', 'permalink-manager'),
50
  'post_status' => __('Post status', 'permalink-manager'),
51
- );
52
-
53
- // Additional function when WPML is enabled
54
- if(class_exists('SitePress')) {
55
- $columns['post_lang'] = __('Language', 'permalink_manager');
56
- }
57
-
58
- return $columns;
59
  }
60
 
61
  /**
@@ -84,6 +82,9 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
84
  $field_args_base = array('type' => 'text', 'value' => $uri, 'without_label' => true, 'input_class' => '');
85
  $permalink = get_permalink($item['ID']);
86
 
 
 
 
87
  switch( $column_name ) {
88
  case 'post_status':
89
  $post_statuses_array = get_post_statuses();
@@ -107,12 +108,8 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
107
  $output .= '</div>';
108
  return $output;
109
 
110
- case 'post_lang':
111
- $post_lang_details = apply_filters('wpml_post_language_details', NULL, $item['ID']);
112
- return (!empty($post_lang_details['native_name'])) ? $post_lang_details['native_name'] : "-";
113
-
114
  default:
115
- return $item[$column_name];
116
  }
117
  }
118
 
@@ -132,19 +129,51 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
132
  * The button that allows to save updated slugs
133
  */
134
  function extra_tablenav( $which ) {
 
 
135
  $button_top = __( 'Update all the URIs below', 'permalink-manager' );
136
  $button_bottom = __( 'Update all the URIs above', 'permalink-manager' );
137
 
138
- echo '<div class="alignleft actions">';
139
- submit_button( ${"button_$which"}, 'primary', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
140
- echo '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
142
 
143
  /**
144
  * Prepare the items for the table to process
145
  */
146
  public function prepare_items() {
147
- global $wpdb, $permalink_manager_options, $active_subsection;
148
 
149
  $columns = $this->get_columns();
150
  $hidden = $this->get_hidden_columns();
@@ -153,19 +182,24 @@ class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
153
 
154
  // Get query variables
155
  $per_page = $permalink_manager_options['screen-options']['per_page'];
156
- $post_types_array = $permalink_manager_options['screen-options']['post_types'];
157
- $post_types = ($active_subsection && $active_subsection == 'all') ? "'" . implode("', '", $post_types_array) . "'" : "'{$active_subsection}'" ;
158
- $post_statuses_array = $permalink_manager_options['screen-options']['post_statuses'];
159
- $post_statuses = "'" . implode("', '", $post_statuses_array) . "'";
160
 
161
  // SQL query parameters
162
  $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
163
  $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
164
  $offset = ($current_page - 1) * $per_page;
165
 
 
 
 
 
 
 
 
 
 
166
  // Grab posts from database
167
- //$sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order LIMIT $per_page OFFSET $offset";
168
- $sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($post_statuses) AND post_type IN ($post_types) ORDER BY $orderby $order";
169
  $all_data = $wpdb->get_results($sql_query, ARRAY_A);
170
 
171
  // How many items?
5
  */
6
  class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
7
 
8
+ public $displayed_post_types, $displayed_post_statuses;
9
+
10
  public function __construct() {
11
+ global $status, $page, $permalink_manager_options, $active_subsection;
12
 
13
  parent::__construct(array(
14
  'singular' => 'slug',
15
  'plural' => 'slugs'
16
  ));
17
+
18
+ $this->displayed_post_statuses = (isset($permalink_manager_options['screen-options']['post_statuses'])) ? "'" . implode("', '", $permalink_manager_options['screen-options']['post_statuses']) . "'" : "'no-post-status'";
19
+ $this->displayed_post_types = ($active_subsection && $active_subsection == 'all') ? "'" . implode("', '", $permalink_manager_options['screen-options']['post_types']) . "'" : "'{$active_subsection}'";
20
  }
21
 
22
  /**
46
  * Override the parent columns method. Defines the columns to use in your listing table
47
  */
48
  public function get_columns() {
49
+ return apply_filters('permalink-manager-uri-editor-columns', array(
50
  //'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
51
  'post_title' => __('Post title', 'permalink-manager'),
52
  'post_name' => __('Post name (native slug)', 'permalink-manager'),
53
  //'post_date_gmt' => __('Date', 'permalink-manager'),
54
  'uri' => __('Full URI & Permalink', 'permalink-manager'),
55
  'post_status' => __('Post status', 'permalink-manager'),
56
+ ));
 
 
 
 
 
 
 
57
  }
58
 
59
  /**
82
  $field_args_base = array('type' => 'text', 'value' => $uri, 'without_label' => true, 'input_class' => '');
83
  $permalink = get_permalink($item['ID']);
84
 
85
+ $output = apply_filters('permalink-manager-uri-editor-column-content', '', $column_name, get_post($item['ID']));
86
+ if(!empty($output)) { return $output; }
87
+
88
  switch( $column_name ) {
89
  case 'post_status':
90
  $post_statuses_array = get_post_statuses();
108
  $output .= '</div>';
109
  return $output;
110
 
 
 
 
 
111
  default:
112
+ return $item[$column_name];
113
  }
114
  }
115
 
129
  * The button that allows to save updated slugs
130
  */
131
  function extra_tablenav( $which ) {
132
+ global $wpdb, $active_section, $active_subsection;
133
+
134
  $button_top = __( 'Update all the URIs below', 'permalink-manager' );
135
  $button_bottom = __( 'Update all the URIs above', 'permalink-manager' );
136
 
137
+ $html = "<div class=\"alignleft actions\">";
138
+ $html .= get_submit_button( ${"button_$which"}, 'primary alignleft', "update_all_slugs[{$which}]", false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
139
+
140
+ if ($which == "top") {
141
+ $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);
142
+ if($months) {
143
+
144
+ $month_key = 'month';
145
+ $screen = get_current_screen();
146
+ $current_url = add_query_arg( array(
147
+ 'page' => PERMALINK_MANAGER_PLUGIN_SLUG,
148
+ 'section' => $active_section,
149
+ 'subsection' => $active_subsection
150
+ ), admin_url($screen->parent_file));
151
+
152
+ $html .= "<div id=\"months-filter\" class=\"alignright hide-if-no-js\" data-filter-url=\"{$current_url}\">";
153
+ $html .= "<select id=\"months-filter-select\" name=\"{$month_key}\">";
154
+ $html .= sprintf("<option value=\"\">%s</option>", __("All dates", "permalink-manager"));
155
+ foreach($months as $month) {
156
+ $month_raw = "{$month['y']}-{$month['m']}";
157
+ $month_human_name = date_i18n("F Y", strtotime($month_raw));
158
+
159
+ $selected = (!empty($_REQUEST[$month_key])) ? selected($_REQUEST[$month_key], $month_raw, false) : "";
160
+ $html .= "<option value=\"{$month_raw}\" {$selected}>{$month_human_name}</option>";
161
+ }
162
+ $html .= "</select>";
163
+ $html .= sprintf("<input id=\"months-filter-button\" class=\"button\" value=\"%s\" type=\"submit\">", __("Filter", "permalink-manager"));
164
+ $html .= "</div>";
165
+ }
166
+ }
167
+ $html .= "</div>";
168
+
169
+ echo $html;
170
  }
171
 
172
  /**
173
  * Prepare the items for the table to process
174
  */
175
  public function prepare_items() {
176
+ global $wpdb, $permalink_manager_options;
177
 
178
  $columns = $this->get_columns();
179
  $hidden = $this->get_hidden_columns();
182
 
183
  // Get query variables
184
  $per_page = $permalink_manager_options['screen-options']['per_page'];
 
 
 
 
185
 
186
  // SQL query parameters
187
  $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'desc';
188
  $orderby = (isset($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'ID';
189
  $offset = ($current_page - 1) * $per_page;
190
 
191
+ // Extra filters
192
+ $extra_filters = '';
193
+ if(!empty($_GET['month'])) {
194
+ $month = date("n", strtotime($_GET['month']));
195
+ $year = date("Y", strtotime($_GET['month']));
196
+
197
+ $extra_filters .= "AND month(post_date) = {$month} AND year(post_date) = {$year}";
198
+ }
199
+
200
  // Grab posts from database
201
+ //$sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types) ORDER BY $orderby $order LIMIT $per_page OFFSET $offset";
202
+ $sql_query = "SELECT * FROM {$wpdb->posts} WHERE post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types) {$extra_filters} ORDER BY $orderby $order";
203
  $all_data = $wpdb->get_results($sql_query, ARRAY_A);
204
 
205
  // How many items?
includes/views/permalink-manager-uri-editor.php CHANGED
@@ -4,9 +4,18 @@
4
  * Display slug editor for Posts, Pages & Custom Post Types
5
  */
6
  class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
 
7
 
8
  public function __construct() {
9
  add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
 
 
 
 
 
 
 
 
10
  }
11
 
12
  /**
@@ -15,8 +24,8 @@ class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
15
  public function add_admin_section($admin_sections) {
16
  global $permalink_manager_options;
17
 
18
- $admin_sections['slug_editor'] = array(
19
- 'name' => __('Permalink editor', 'permalink-manager')
20
  );
21
 
22
  // Display separate section for each post type
@@ -27,7 +36,7 @@ class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
27
 
28
  $icon = (class_exists('WooCommerce') && in_array($post_type_name, array('product'))) ? "<i class=\"woocommerce-icon woocommerce-cart\"></i>" : "";
29
 
30
- $admin_sections['slug_editor']['subsections'][$post_type_name] = array(
31
  'name' => "{$icon} {$post_type['label']}",
32
  'function' => array('class' => 'Permalink_Manager_URI_Editor_Post', 'method' => 'display_admin_section')
33
  );
@@ -42,7 +51,7 @@ class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
42
  // Get the icon
43
  $icon = (class_exists('WooCommerce') && in_array($taxonomy_name, array('product_tag', 'product_cat'))) ? "<i class=\"woocommerce-icon woocommerce-cart\"></i>" : "<i class=\"dashicons dashicons-tag\"></i>";
44
 
45
- $admin_sections['slug_editor']['subsections']["tax_{$taxonomy_name}"] = array(
46
  'name' => "{$icon} {$taxonomy['label']}",
47
  'html' => Permalink_Manager_Admin_Functions::pro_text(),
48
  'pro' => true
@@ -52,14 +61,51 @@ class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
52
  // A little dirty hack to move wooCommerce product & taxonomies to the end of array
53
  if(class_exists('WooCommerce')) {
54
  foreach(array('product', 'tax_product_tag', 'tax_product_cat') as $section_name) {
55
- if(empty($admin_sections['slug_editor']['subsections'][$section_name])) { continue; }
56
- $section = $admin_sections['slug_editor']['subsections'][$section_name];
57
- unset($admin_sections['slug_editor']['subsections'][$section_name]);
58
- $admin_sections['slug_editor']['subsections'][$section_name] = $section;
59
  }
60
  }
61
 
62
  return $admin_sections;
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
4
  * Display slug editor for Posts, Pages & Custom Post Types
5
  */
6
  class Permalink_Manager_Uri_Editor extends Permalink_Manager_Class {
7
+ public $this_section = 'uri_editor';
8
 
9
  public function __construct() {
10
  add_filter( 'permalink-manager-sections', array($this, 'add_admin_section'), 1 );
11
+ add_filter( 'screen_settings', array($this, 'screen_options'), 99, 2 );
12
+ }
13
+
14
+ public function init() {
15
+ global $permalink_manager_admin_page;
16
+
17
+ // Show "screen options"
18
+ add_action("load-{$permalink_manager_admin_page}", array($this, "screen_options"));
19
  }
20
 
21
  /**
24
  public function add_admin_section($admin_sections) {
25
  global $permalink_manager_options;
26
 
27
+ $admin_sections[$this->this_section] = array(
28
+ 'name' => __('URI editor', 'permalink-manager')
29
  );
30
 
31
  // Display separate section for each post type
36
 
37
  $icon = (class_exists('WooCommerce') && in_array($post_type_name, array('product'))) ? "<i class=\"woocommerce-icon woocommerce-cart\"></i>" : "";
38
 
39
+ $admin_sections[$this->this_section]['subsections'][$post_type_name] = array(
40
  'name' => "{$icon} {$post_type['label']}",
41
  'function' => array('class' => 'Permalink_Manager_URI_Editor_Post', 'method' => 'display_admin_section')
42
  );
51
  // Get the icon
52
  $icon = (class_exists('WooCommerce') && in_array($taxonomy_name, array('product_tag', 'product_cat'))) ? "<i class=\"woocommerce-icon woocommerce-cart\"></i>" : "<i class=\"dashicons dashicons-tag\"></i>";
53
 
54
+ $admin_sections[$this->this_section]['subsections']["tax_{$taxonomy_name}"] = array(
55
  'name' => "{$icon} {$taxonomy['label']}",
56
  'html' => Permalink_Manager_Admin_Functions::pro_text(),
57
  'pro' => true
61
  // A little dirty hack to move wooCommerce product & taxonomies to the end of array
62
  if(class_exists('WooCommerce')) {
63
  foreach(array('product', 'tax_product_tag', 'tax_product_cat') as $section_name) {
64
+ if(empty($admin_sections[$this->this_section]['subsections'][$section_name])) { continue; }
65
+ $section = $admin_sections[$this->this_section]['subsections'][$section_name];
66
+ unset($admin_sections[$this->this_section]['subsections'][$section_name]);
67
+ $admin_sections[$this->this_section]['subsections'][$section_name] = $section;
68
  }
69
  }
70
 
71
  return $admin_sections;
72
  }
73
 
74
+ /**
75
+ * Add scren options
76
+ */
77
+ public function screen_options($html, $screen) {
78
+ global $active_section;
79
+
80
+ // Display the screen options only in "Permalink Editor"
81
+ if($active_section != $this->this_section) { return $html; }
82
+
83
+ $button = get_submit_button( __( 'Apply', 'permalink-manager' ), 'primary', 'screen-options-apply', false );
84
+ $html = "<fieldset class=\"permalink-manager-screen-options\">";
85
+
86
+ $screen_options = array(
87
+ 'per_page' => array(
88
+ 'type' => 'number',
89
+ 'label' => __('Per page', 'permalink-manager'),
90
+ 'input_class' => 'settings-select'
91
+ ),
92
+ 'post_statuses' => array(
93
+ 'type' => 'checkbox',
94
+ 'label' => __('Post statuses', 'permalink-manager'),
95
+ 'choices' => get_post_statuses(),
96
+ 'select_all' => '',
97
+ 'unselect_all' => '',
98
+ )
99
+ );
100
+
101
+ foreach($screen_options as $field_name => $field_args) {
102
+ $field_args['container'] = 'screen-options';
103
+ $html .= Permalink_Manager_Admin_Functions::generate_option_field("screen-options[{$field_name}]", $field_args);
104
+ }
105
+
106
+ $html .= "</fieldset>{$button}";
107
+
108
+ return $html;
109
+ }
110
+
111
  }
languages/permalink-manager.pot CHANGED
@@ -1,216 +1,492 @@
1
- # Loco Gettext template
2
- #, fuzzy
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Permalink Manager\n"
6
- "Report-Msgid-Bugs-To: \n"
7
- "POT-Creation-Date: Fri Jan 08 2016 20:08:17 GMT+0100 (CET)\n"
8
- "POT-Revision-Date: Fri Jan 08 2016 20:08:23 GMT+0100 (CET)\n"
9
- "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10
- "Last-Translator: \n"
11
- "Language-Team: \n"
12
- "Language: \n"
13
- "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION\n"
14
- "MIME-Version: 1.0\n"
15
- "Content-Type: text/plain; charset=UTF-8\n"
16
- "Content-Transfer-Encoding: 8bit\n"
17
- "X-Poedit-SourceCharset: UTF-8\n"
18
- "X-Poedit-Basepath: .\n"
19
- "X-Poedit-SearchPath-0: ..\n"
20
- "X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
21
- "__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
22
- "_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
23
- "esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
24
- "esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
25
- "X-Generator: Loco - https://localise.biz/"
26
-
27
- #. Name of the plugin
28
- msgid "Permalink Manager"
29
- msgstr ""
30
-
31
- #. URI of the plugin
32
- msgid "http://maciejbis.net"
33
- msgstr ""
34
-
35
- #. Description of the plugin
36
- msgid ""
37
- "A simple tool that allows to mass update of slugs that are used to build "
38
- "permalinks for Posts, Pages and Custom Post Types."
39
- msgstr ""
40
-
41
- #. Author of the plugin
42
- msgid "Maciej Bis"
43
- msgstr ""
44
-
45
- #: ../permalink-manager.php:89
46
- msgid "Find & Replace"
47
- msgstr ""
48
-
49
- #: ../permalink-manager.php:108
50
- msgid "Regenerate"
51
- msgstr ""
52
-
53
- #: ../permalink-manager.php:135
54
- msgid "Permalinks"
55
- msgstr ""
56
-
57
- #: ../permalink-manager.php:137
58
- msgid ""
59
- "You can disable/enable selected post types from the table below using "
60
- "<strong>\"Screen Options\"</strong> (click on the upper-right button to show "
61
- "it) section above."
62
- msgstr ""
63
-
64
- #: ../permalink-manager.php:140
65
- msgid "Find and replace"
66
- msgstr ""
67
-
68
- #: ../permalink-manager.php:142 ../permalink-manager.php:147
69
- msgid "<strong>You are doing it at your own risk!</strong>"
70
- msgstr ""
71
-
72
- #: ../permalink-manager.php:142
73
- msgid ""
74
- "A backup of MySQL database before using this tool is highly recommended. The "
75
- "search & replace operation might be not revertible!"
76
- msgstr ""
77
-
78
- #: ../permalink-manager.php:145
79
- msgid "Regenerate slugs"
80
- msgstr ""
81
-
82
- #: ../permalink-manager.php:147
83
- msgid ""
84
- "A backup of MySQL database before using this tool is highly recommended. The "
85
- "regenerate process of slugs might be not revertible!"
86
- msgstr ""
87
-
88
- #: ../permalink-manager.php:160
89
- msgid "by Maciej Bis"
90
- msgstr ""
91
-
92
- #: ../permalink-manager.php:210
93
- msgid "Go To Permalink Manager"
94
- msgstr ""
95
-
96
- #: ../permalink-manager.php:226
97
- msgid "Post Types"
98
- msgstr ""
99
-
100
- #: ../permalink-manager.php:228 ../permalink-manager.php:257 ../permalink-manager.
101
- #: php:273
102
- msgid "All Post Types"
103
- msgstr ""
104
-
105
- #: ../permalink-manager.php:232
106
- msgid "Post Statuses"
107
- msgstr ""
108
-
109
- #: ../permalink-manager.php:234 ../permalink-manager.php:263 ../permalink-manager.
110
- #: php:279
111
- msgid "All Post Statuses"
112
- msgstr ""
113
-
114
- #: ../permalink-manager.php:238
115
- msgid "Per page"
116
- msgstr ""
117
-
118
- #: ../permalink-manager.php:247
119
- msgid "Find ..."
120
- msgstr ""
121
-
122
- #: ../permalink-manager.php:251
123
- msgid "Replace with ..."
124
- msgstr ""
125
-
126
- #: ../permalink-manager.php:255 ../permalink-manager.php:271
127
- msgid "Post Types that should be affected"
128
- msgstr ""
129
-
130
- #: ../permalink-manager.php:261 ../permalink-manager.php:277
131
- msgid "Post Statuses that should be affected"
132
- msgstr ""
133
-
134
- #: ../permalink-manager.php:347
135
- #, php-format
136
- msgid "<strong>\"%1s\"</strong> field is empty!"
137
- msgstr ""
138
-
139
- #: ../permalink-manager.php:418
140
- #, php-format
141
- msgid "<strong>%d</strong> slug were updated!"
142
- msgid_plural "<strong>%d</strong> slugs were updated!"
143
- msgstr[0] ""
144
- msgstr[1] ""
145
-
146
- #: ../permalink-manager.php:419
147
- #, php-format
148
- msgid "<a href=\"%s\">Click here</a> to go to the list of updated slugs"
149
- msgstr ""
150
-
151
- #: ../permalink-manager.php:422
152
- msgid "<strong>No slugs</strong> were updated!"
153
- msgstr ""
154
-
155
- #: ../permalink-manager.php:435 ../permalink-manager.php:447 ../inc/permalink-
156
- #: manager-wp-table.php:30
157
- msgid "Title"
158
- msgstr ""
159
-
160
- #: ../permalink-manager.php:436 ../permalink-manager.php:448
161
- msgid "Old slug"
162
- msgstr ""
163
-
164
- #: ../permalink-manager.php:437 ../permalink-manager.php:449
165
- msgid "New slug"
166
- msgstr ""
167
-
168
- #: ../permalink-manager.php:447
169
- msgid "Show more details"
170
- msgstr ""
171
-
172
- #: ../permalink-manager.php:454
173
- msgid "List of updated posts"
174
- msgstr ""
175
-
176
- #: ../inc/permalink-manager-screen-options.php:21
177
- msgid "Apply"
178
- msgstr ""
179
-
180
- #: ../inc/permalink-manager-wp-table.php:31
181
- msgid "Slug"
182
- msgstr ""
183
-
184
- #: ../inc/permalink-manager-wp-table.php:32
185
- msgid "Date"
186
- msgstr ""
187
-
188
- #: ../inc/permalink-manager-wp-table.php:33
189
- msgid "Permalink"
190
- msgstr ""
191
-
192
- #: ../inc/permalink-manager-wp-table.php:34
193
- msgid "Post Status"
194
- msgstr ""
195
-
196
- #: ../inc/permalink-manager-wp-table.php:35
197
- msgid "Post Type"
198
- msgstr ""
199
-
200
- #: ../inc/permalink-manager-wp-table.php:81 ../inc/permalink-manager-wp-table.php:
201
- #: 81
202
- msgid "Edit"
203
- msgstr ""
204
-
205
- #: ../inc/permalink-manager-wp-table.php:82 ../inc/permalink-manager-wp-table.php:
206
- #: 82
207
- msgid "View"
208
- msgstr ""
209
-
210
- #: ../inc/permalink-manager-wp-table.php:124
211
- msgid "Update all slugs below"
212
- msgstr ""
213
-
214
- #: ../inc/permalink-manager-wp-table.php:125
215
- msgid "Update all slugs above"
216
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #, fuzzy
2
+ msgid ""
3
+ msgstr ""
4
+ "Project-Id-Version: PACKAGE VERSION\n"
5
+ "Report-Msgid-Bugs-To: \n"
6
+ "POT-Creation-Date: 2017-06-07 00:37+0000\n"
7
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
8
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
9
+ "Language-Team: \n"
10
+ "Language: \n"
11
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Loco https://localise.biz/"
16
+
17
+ #: permalink-manager.php:172
18
+ #, php-format
19
+ msgid ""
20
+ "Need to change the permalinks for categories, tags, custom taxonomies or "
21
+ "WooCommerce?<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" "
22
+ "target=\"_blank\">here</a> and enjoy the additional features!</strong>"
23
+ msgstr ""
24
+
25
+ #: includes/views/permalink-manager-uri-editor.php:28
26
+ msgid "URI editor"
27
+ msgstr ""
28
+
29
+ #: includes/views/permalink-manager-uri-editor.php:83
30
+ msgid "Apply"
31
+ msgstr ""
32
+
33
+ #: includes/views/permalink-manager-uri-editor.php:89
34
+ msgid "Per page"
35
+ msgstr ""
36
+
37
+ #: includes/views/permalink-manager-uri-editor.php:94
38
+ msgid "Post statuses"
39
+ msgstr ""
40
+
41
+ #: includes/views/permalink-manager-uri-editor-post.php:51
42
+ msgid "Post title"
43
+ msgstr ""
44
+
45
+ #: includes/views/permalink-manager-uri-editor-post.php:52
46
+ msgid "Post name (native slug)"
47
+ msgstr ""
48
+
49
+ #: includes/views/permalink-manager-uri-editor-post.php:54
50
+ msgid "Full URI & Permalink"
51
+ msgstr ""
52
+
53
+ #: includes/views/permalink-manager-uri-editor-post.php:55
54
+ msgid "Post status"
55
+ msgstr ""
56
+
57
+ #: includes/views/permalink-manager-uri-editor-post.php:105
58
+ #: includes/views/permalink-manager-uri-editor-post.php:105
59
+ msgid "Edit"
60
+ msgstr ""
61
+
62
+ #: includes/views/permalink-manager-uri-editor-post.php:106
63
+ #: includes/views/permalink-manager-uri-editor-post.php:106
64
+ msgid "View"
65
+ msgstr ""
66
+
67
+ #: includes/views/permalink-manager-uri-editor-post.php:134
68
+ msgid "Update all the URIs below"
69
+ msgstr ""
70
+
71
+ #: includes/views/permalink-manager-uri-editor-post.php:135
72
+ msgid "Update all the URIs above"
73
+ msgstr ""
74
+
75
+ #: includes/views/permalink-manager-uri-editor-post.php:154
76
+ msgid "All dates"
77
+ msgstr ""
78
+
79
+ #: includes/views/permalink-manager-uri-editor-post.php:163
80
+ msgid "Filter"
81
+ msgstr ""
82
+
83
+ #: includes/views/permalink-manager-debug.php:14
84
+ msgid "Debug"
85
+ msgstr ""
86
+
87
+ #: includes/views/permalink-manager-debug.php:31
88
+ msgid "Debug data"
89
+ msgstr ""
90
+
91
+ #: includes/views/permalink-manager-debug.php:35
92
+ msgid "List of the URIs generated by this plugin."
93
+ msgstr ""
94
+
95
+ #: includes/views/permalink-manager-debug.php:36
96
+ msgid "Array with URIs"
97
+ msgstr ""
98
+
99
+ #: includes/views/permalink-manager-debug.php:42
100
+ msgid "List of the permastructures."
101
+ msgstr ""
102
+
103
+ #: includes/views/permalink-manager-debug.php:43
104
+ msgid "Array with permastructures"
105
+ msgstr ""
106
+
107
+ #: includes/views/permalink-manager-debug.php:49
108
+ msgid "Currently used plugin settings."
109
+ msgstr ""
110
+
111
+ #: includes/views/permalink-manager-debug.php:50
112
+ msgid "Array with settings used in this plugin."
113
+ msgstr ""
114
+
115
+ #: includes/views/permalink-manager-debug.php:56
116
+ msgid "Permalink hooks."
117
+ msgstr ""
118
+
119
+ #: includes/views/permalink-manager-debug.php:57
120
+ msgid "Array with list of permalink hooks used on this website."
121
+ msgstr ""
122
+
123
+ #: includes/views/permalink-manager-tools.php:15
124
+ msgid "Tools"
125
+ msgstr ""
126
+
127
+ #: includes/views/permalink-manager-tools.php:18
128
+ #: includes/views/permalink-manager-tools.php:116
129
+ msgid "Find and replace"
130
+ msgstr ""
131
+
132
+ #: includes/views/permalink-manager-tools.php:22
133
+ msgid "Regenerate/Reset"
134
+ msgstr ""
135
+
136
+ #: includes/views/permalink-manager-tools.php:26
137
+ msgid "Stop words"
138
+ msgstr ""
139
+
140
+ #: includes/views/permalink-manager-tools.php:36
141
+ msgid ""
142
+ "<strong>A MySQL backup is highly recommended before using \"<em>Native "
143
+ "slugs</em>\" mode!</strong>"
144
+ msgstr ""
145
+
146
+ #: includes/views/permalink-manager-tools.php:47
147
+ msgid "Find ..."
148
+ msgstr ""
149
+
150
+ #: includes/views/permalink-manager-tools.php:53
151
+ msgid "Replace with ..."
152
+ msgstr ""
153
+
154
+ #: includes/views/permalink-manager-tools.php:59
155
+ #: includes/views/permalink-manager-tools.php:129
156
+ msgid "Mode"
157
+ msgstr ""
158
+
159
+ #: includes/views/permalink-manager-tools.php:62
160
+ #: includes/views/permalink-manager-tools.php:132
161
+ msgid "Custom URIs"
162
+ msgstr ""
163
+
164
+ #: includes/views/permalink-manager-tools.php:62
165
+ #: includes/views/permalink-manager-tools.php:132
166
+ msgid "Native slugs"
167
+ msgstr ""
168
+
169
+ #: includes/views/permalink-manager-tools.php:65
170
+ #: includes/views/permalink-manager-tools.php:135
171
+ msgid "Select content type"
172
+ msgstr ""
173
+
174
+ #: includes/views/permalink-manager-tools.php:71
175
+ #: includes/views/permalink-manager-tools.php:141
176
+ #: includes/views/permalink-manager-permastructs.php:36
177
+ msgid "Post types"
178
+ msgstr ""
179
+
180
+ #: includes/views/permalink-manager-tools.php:71
181
+ #: includes/views/permalink-manager-tools.php:141
182
+ #: includes/views/permalink-manager-permastructs.php:42
183
+ msgid "Taxonomies"
184
+ msgstr ""
185
+
186
+ #: includes/views/permalink-manager-tools.php:74
187
+ #: includes/views/permalink-manager-tools.php:144
188
+ msgid "Select post types"
189
+ msgstr ""
190
+
191
+ #: includes/views/permalink-manager-tools.php:83
192
+ #: includes/views/permalink-manager-tools.php:153
193
+ msgid "Select taxonomies"
194
+ msgstr ""
195
+
196
+ #: includes/views/permalink-manager-tools.php:94
197
+ #: includes/views/permalink-manager-tools.php:164
198
+ msgid "Select post statuses"
199
+ msgstr ""
200
+
201
+ #: includes/views/permalink-manager-tools.php:103
202
+ #: includes/views/permalink-manager-tools.php:173
203
+ msgid "Select IDs"
204
+ msgstr ""
205
+
206
+ #: includes/views/permalink-manager-tools.php:107
207
+ #: includes/views/permalink-manager-tools.php:177
208
+ msgid ""
209
+ "To narrow the above filters you can type the post IDs (or ranges) here. Eg. "
210
+ "<strong>1-8, 10, 25</strong>."
211
+ msgstr ""
212
+
213
+ #: includes/views/permalink-manager-tools.php:113
214
+ #: includes/views/permalink-manager-tools.php:183
215
+ msgid "Important notices"
216
+ msgstr ""
217
+
218
+ #: includes/views/permalink-manager-tools.php:186
219
+ msgid "Regenerate"
220
+ msgstr ""
221
+
222
+ #: includes/views/permalink-manager-settings.php:14
223
+ msgid "Settings"
224
+ msgstr ""
225
+
226
+ #: includes/views/permalink-manager-settings.php:32
227
+ msgid "General & Interface"
228
+ msgstr ""
229
+
230
+ #: includes/views/permalink-manager-settings.php:37
231
+ msgid "Auto-update URIs"
232
+ msgstr ""
233
+
234
+ #: includes/views/permalink-manager-settings.php:39
235
+ msgid ""
236
+ "If enabled the custom URIs will be automatically updated every time the post "
237
+ "is saved or updated."
238
+ msgstr ""
239
+
240
+ #: includes/views/permalink-manager-settings.php:43
241
+ msgid "Force custom slugs"
242
+ msgstr ""
243
+
244
+ #: includes/views/permalink-manager-settings.php:45
245
+ msgid ""
246
+ "If enabled the native slugs in the defult URIs will be recreated from the "
247
+ "post title.<br />This may cause URI duplicates when the post title is used "
248
+ "more than once."
249
+ msgstr ""
250
+
251
+ #: includes/views/permalink-manager-settings.php:50
252
+ msgid "Miscellaneous & SEO functions"
253
+ msgstr ""
254
+
255
+ #: includes/views/permalink-manager-settings.php:55
256
+ msgid "Primay term/category support"
257
+ msgstr ""
258
+
259
+ #: includes/views/permalink-manager-settings.php:57
260
+ msgid ""
261
+ "Used to generate default permalinks in pages, posts & custom post types. "
262
+ "Works only when \"Yoast SEO\" plugin is enabled."
263
+ msgstr ""
264
+
265
+ #: includes/views/permalink-manager-settings.php:61
266
+ msgid "Canonical redirect"
267
+ msgstr ""
268
+
269
+ #: includes/views/permalink-manager-settings.php:63
270
+ msgid ""
271
+ "This function allows Wordpress to correct the URLs used by the visitors."
272
+ msgstr ""
273
+
274
+ #: includes/views/permalink-manager-settings.php:67
275
+ msgid "Redirect"
276
+ msgstr ""
277
+
278
+ #: includes/views/permalink-manager-settings.php:69
279
+ msgid "Disable"
280
+ msgstr ""
281
+
282
+ #: includes/views/permalink-manager-settings.php:69
283
+ msgid "Enable \"301 redirect\""
284
+ msgstr ""
285
+
286
+ #: includes/views/permalink-manager-settings.php:69
287
+ msgid "Enable \"302 redirect\""
288
+ msgstr ""
289
+
290
+ #: includes/views/permalink-manager-settings.php:70
291
+ msgid ""
292
+ "If enabled - the visitors will be redirected from native permalinks to your "
293
+ "custom permalinks. Please note that the redirects will work correctly only "
294
+ "if native slug \"post name\" will not be changed."
295
+ msgstr ""
296
+
297
+ #: includes/views/permalink-manager-settings.php:76
298
+ msgid "Save settings"
299
+ msgstr ""
300
+
301
+ #: includes/views/permalink-manager-permastructs.php:15
302
+ msgid "Permastructures"
303
+ msgstr ""
304
+
305
+ #: includes/views/permalink-manager-permastructs.php:29
306
+ #, php-format
307
+ msgid ""
308
+ "All available <a href=\"%s\" target=\"_blank\">structure tags</a> for "
309
+ "<strong>post types</strong> allowed are listed below."
310
+ msgstr ""
311
+
312
+ #: includes/views/permalink-manager-permastructs.php:31
313
+ msgid ""
314
+ "Please note that some of them can be used only for particular post types' "
315
+ "settings."
316
+ msgstr ""
317
+
318
+ #: includes/views/permalink-manager-permastructs.php:52
319
+ msgid "WooCommerce"
320
+ msgstr ""
321
+
322
+ #: includes/views/permalink-manager-permastructs.php:87
323
+ msgid "Save permastructures"
324
+ msgstr ""
325
+
326
+ #: includes/core/permalink-manager-third-parties.php:94
327
+ msgid "Language"
328
+ msgstr ""
329
+
330
+ #: includes/core/permalink-manager-uri-functions-post.php:465
331
+ #: includes/core/permalink-manager-uri-functions-post.php:469
332
+ msgid "Yes"
333
+ msgstr ""
334
+
335
+ #: includes/core/permalink-manager-uri-functions-post.php:465
336
+ #: includes/core/permalink-manager-uri-functions-post.php:468
337
+ msgid "No"
338
+ msgstr ""
339
+
340
+ #: includes/core/permalink-manager-uri-functions-post.php:467
341
+ #, php-format
342
+ msgid "Use global settings [%s]"
343
+ msgstr ""
344
+
345
+ #. Name of the plugin
346
+ #: includes/core/permalink-manager-uri-functions-post.php:473
347
+ #: includes/core/permalink-manager-uri-functions-post.php:477
348
+ #: includes/core/permalink-manager-uri-functions-post.php:478
349
+ #: includes/core/permalink-manager-admin-functions.php:79
350
+ #: includes/core/permalink-manager-admin-functions.php:79
351
+ msgid "Permalink Manager"
352
+ msgstr ""
353
+
354
+ #: includes/core/permalink-manager-uri-functions-post.php:477
355
+ msgid "Close: "
356
+ msgstr ""
357
+
358
+ #: includes/core/permalink-manager-uri-functions-post.php:483
359
+ msgid "Current URI"
360
+ msgstr ""
361
+
362
+ #: includes/core/permalink-manager-uri-functions-post.php:484
363
+ msgid ""
364
+ "The custom URI can be edited only if 'Auto-update the URI' feature is not "
365
+ "enabled."
366
+ msgstr ""
367
+
368
+ #: includes/core/permalink-manager-uri-functions-post.php:488
369
+ msgid "Auto-update the URI"
370
+ msgstr ""
371
+
372
+ #: includes/core/permalink-manager-uri-functions-post.php:489
373
+ msgid ""
374
+ "If enabled, the 'Current URI' field will be automatically changed to "
375
+ "'Default URI' (displayed below) after the post is saved or updated."
376
+ msgstr ""
377
+
378
+ #: includes/core/permalink-manager-uri-functions-post.php:494
379
+ msgid "Default URI"
380
+ msgstr ""
381
+
382
+ #: includes/core/permalink-manager-uri-functions-post.php:495
383
+ msgid "Restore to Default URI"
384
+ msgstr ""
385
+
386
+ #: includes/core/permalink-manager-actions.php:24
387
+ msgid "Sitemap was updated!"
388
+ msgstr ""
389
+
390
+ #: includes/core/permalink-manager-actions.php:59
391
+ #, php-format
392
+ msgid "<strong>%d</strong> slug was updated!"
393
+ msgid_plural "<strong>%d</strong> slugs were updated!"
394
+ msgstr[0] ""
395
+ msgstr[1] ""
396
+
397
+ #: includes/core/permalink-manager-actions.php:60
398
+ #, php-format
399
+ msgid "<a %s>Click here</a> to go to the list of updated slugs"
400
+ msgstr ""
401
+
402
+ #: includes/core/permalink-manager-actions.php:65
403
+ msgid "<strong>No slugs</strong> were updated!"
404
+ msgstr ""
405
+
406
+ #: includes/core/permalink-manager-actions.php:99
407
+ msgid "The settings are saved!"
408
+ msgstr ""
409
+
410
+ #: includes/core/permalink-manager-admin-functions.php:114
411
+ msgid "URI Editor"
412
+ msgstr ""
413
+
414
+ #: includes/core/permalink-manager-admin-functions.php:116
415
+ #: includes/core/permalink-manager-admin-functions.php:391
416
+ msgid "Buy Permalink Manager Pro"
417
+ msgstr ""
418
+
419
+ #: includes/core/permalink-manager-admin-functions.php:181
420
+ msgid "Select all"
421
+ msgstr ""
422
+
423
+ #: includes/core/permalink-manager-admin-functions.php:182
424
+ msgid "Unselect all"
425
+ msgstr ""
426
+
427
+ #: includes/core/permalink-manager-admin-functions.php:392
428
+ msgid "Donate"
429
+ msgstr ""
430
+
431
+ #: includes/core/permalink-manager-admin-functions.php:393
432
+ msgid "by Maciej Bis"
433
+ msgstr ""
434
+
435
+ #: includes/core/permalink-manager-admin-functions.php:467
436
+ #, php-format
437
+ msgid ""
438
+ "This functionality is available only in <a href=\"%s\" target=\"_blank\">"
439
+ "Permalink Manager Pro</a>."
440
+ msgstr ""
441
+
442
+ #: includes/core/permalink-manager-admin-functions.php:488
443
+ #: includes/core/permalink-manager-admin-functions.php:511
444
+ msgid "Title"
445
+ msgstr ""
446
+
447
+ #: includes/core/permalink-manager-admin-functions.php:489
448
+ #: includes/core/permalink-manager-admin-functions.php:512
449
+ msgid "Old URI"
450
+ msgstr ""
451
+
452
+ #: includes/core/permalink-manager-admin-functions.php:490
453
+ #: includes/core/permalink-manager-admin-functions.php:513
454
+ msgid "New URI"
455
+ msgstr ""
456
+
457
+ #: includes/core/permalink-manager-admin-functions.php:491
458
+ #: includes/core/permalink-manager-admin-functions.php:514
459
+ msgid "Old Slug"
460
+ msgstr ""
461
+
462
+ #: includes/core/permalink-manager-admin-functions.php:492
463
+ #: includes/core/permalink-manager-admin-functions.php:515
464
+ msgid "New Slug"
465
+ msgstr ""
466
+
467
+ #: includes/core/permalink-manager-admin-functions.php:511
468
+ msgid "Show more details"
469
+ msgstr ""
470
+
471
+ #: includes/core/permalink-manager-admin-functions.php:520
472
+ msgid "List of updated items"
473
+ msgstr ""
474
+
475
+ #. Description of the plugin
476
+ msgid ""
477
+ "Most advanced Permalink utility for Wordpress. It allows to bulk edit the "
478
+ "permalinks & permastructures and regenerate/reset all the URIs in your "
479
+ "Wordpress instance."
480
+ msgstr ""
481
+
482
+ #. URI of the plugin
483
+ msgid "https://permalinkmanager.pro?utm_source=plugin"
484
+ msgstr ""
485
+
486
+ #. Author of the plugin
487
+ msgid "Maciej Bis"
488
+ msgstr ""
489
+
490
+ #. Author URI of the plugin
491
+ msgid "http://maciejbis.net/"
492
+ msgstr ""
out/permalink-manager-admin.css CHANGED
@@ -1,78 +1,119 @@
1
  /**
2
  * Permalink Manager CSS
3
  */
4
- #permalink-manager #plugin-name-heading a{color:#959595;font-size:60%;text-decoration:none}
5
- #permalink-manager #permalink-manager-tab-nav > a:first-child{margin-left:0}
6
- #permalink-manager h4{font-size:18px;margin-bottom:10px}
7
- #permalink-manager h5{font-size:15px;margin-bottom:10px}
8
- #permalink-manager .structure-tags-list{display:block;line-height:175%}
9
- #permalink-manager .structure-tags-list code{}
10
- #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
11
- #permalink-manager .settings-select{min-width:200px}
12
- #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
13
- #permalink-manager .margin-top{margin-top:15px}
 
 
14
 
15
- #permalink-manager .woocommerce-icon:before{font-family:"WooCommerce";font-style:normal}
16
- #permalink-manager .woocommerce-cart:before{content:"\e01d"}
17
- #permalink-manager .woocommerce-logo:before{content:"\e03d"}
18
 
19
- #permalink-manager .subsubsub{display:block;width:100%;overflow:hidden;margin-bottom:8px}
20
- #permalink-manager .subsubsub li:before{content:" | "}
21
- #permalink-manager .subsubsub li:first-child:before{content:"";color:#aaa}
22
- #permalink-manager .subsubsub li .dashicons,#permalink-manager .subsubsub li .woocommerce-logo{font-size:100%;line-height:200%;height:auto;width:auto}
23
- #permalink-manager .tablenav{margin:15px 0;height:auto}
24
- #permalink-manager .tablenav.top{margin-top:0}
25
- #permalink-manager .tablenav .actions{padding:0;overflow:visible}
26
- #permalink-manager .column-post_type,#permalink-manager .column-post_status,#permalink-manager .column-count,#permalink-manager .column-post_lang{width:13%}
27
- #permalink-manager .column-count,#permalink-manager th#count{text-align:right}
28
- #permalink-manager th#count a{display:inline-block}
29
- #permalink-manager .post_name input{max-width:100%}
30
- #permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
31
- #permalink-manager .post_permalink{margin-top:5px;display:block}
 
 
32
 
33
- #permalink-manager .info{box-shadow:0 1px 1px 0 rgba(0,0,0,.1);display:block;overflow:hidden;clear:both;font-weight:bold;border-left:4px solid #dc3232;}
34
- #permalink-manager .alert,#permalink-manager .info{line-height:19px;padding:11px 15px;margin:15px 0}
35
- #permalink-manager .alert p,#permalink-manager .info p{margin-top:0;line-height:200%}
36
- #permalink-manager .alert ul,#permalink-manager .alert ol{margin-top:0;margin-bottom:0}
37
- #permalink-manager .alert p:last-of-type,#permalink-manager .alert li:last-of-type,#permalink-manager .info p:last-of-type{margin-bottom:0}
38
- #permalink-manager .warning{background:#dc3232}
39
- #permalink-manager .warning,#permalink-manager .warning a{color:#fff}
40
- #permalink-manager .info{background:#f9f9f9}
41
- #permalink-manager .section-notes,#permalink-manager .short-pre,#permalink-manager .short-textarea{padding:15px;font-size:13px;margin-top:15px;line-height:20px;background:#e5e5e5;border:1px solid #ccc;color:#555}
42
- #permalink-manager .section-notes a,#permalink-manager .section-notes h3{color:#111}
43
- #permalink-manager .section-notes h3,#permalink-manager .section-notes h4{margin-top:0}
44
- #permalink-manager .section-notes h4{font-size:14px}
45
- #permalink-manager .section-notes code{font-size:11px;background:#444;color:#fff}
46
- #permalink-manager .section-notes ol{margin-top:0;margin-bottom:0}
47
- #permalink-manager .section-notes ol li:last-of-type{margin-bottom:0}
48
- #permalink-manager .short-pre,#permalink-manager .short-textarea{height:150px;overflow:auto;max-width:100%;display:block}
49
- #permalink-manager .structure-tags-list{margin-top:15px}
50
 
51
- #permalink-manager .checkbox_actions{padding-top:10px;border-top:1px solid #ddd}
52
- #permalink-manager .extra-links{margin-top:5px;font-size:12px}
53
- #permalink-manager .extra-links a{color:#666;display:inline-block;text-decoration:none}
54
- #permalink-manager .extra-links a:before{content:" | "}
55
- #permalink-manager .extra-links a:first-child:before{content:""}
56
- #permalink-manager .checkboxes{margin-left:-15px;margin-right:15px;overflow:hidden;display:block}
57
- #permalink-manager .checkboxes > label{display:inline-block;width:33%;float:left;padding:0 15px;box-sizing:border-box;padding-bottom:5px}
58
- #permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both}
59
- #permalink-manager .field-description{font-size:12px}
60
- #permalink-manager .appended-row td{padding-left:0;padding-right:0}
 
61
 
62
  /**
63
  * Columns
64
  */
65
- #permalink-manager .columns-container{overflow:hidden;margin-left:-15px;margin-right:-15px;clear:both}
66
- #permalink-manager .columns-container .column{float:left;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-box-sizing:border-box;overflow:hidden}
67
- #permalink-manager .columns-container .column-1_2{width:50%}
68
  #permalink-manager .columns-container .column-1_3{width:33.33%}
69
  #permalink-manager .columns-container .column-2_3{width:66.67%}
 
 
70
 
71
  #slugdiv #post_name{width:100%}
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  /**
74
  * Breakpoints
75
  */
76
- @media only screen and (max-width : 782px) {
 
 
 
77
  #permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-1_3,#permalink-manager .columns-container .column-2_3{width:100%}
78
  }
1
  /**
2
  * Permalink Manager CSS
3
  */
4
+ #permalink-manager #plugin-name-heading .author-link{color:#959595;font-size:60%;text-decoration:none}
5
+ #permalink-manager #permalink-manager-tab-nav > a:first-child{margin-left:0}
6
+ #permalink-manager h4{font-size:18px;margin-bottom:10px}
7
+ #permalink-manager h5{font-size:15px;margin-bottom:10px}
8
+ #permalink-manager .structure-tags-list{display:block;line-height:175%}
9
+ #permalink-manager .structure-tags-list code{}
10
+ #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
11
+ #permalink-manager .settings-select{min-width:200px}
12
+ #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
13
+ #permalink-manager .margin-top{margin-top:15px}
14
+ #permalink-manager .help_tooltip{text-decoration:none;color:#959595}
15
+ #permalink-manager .small-select{height:24px;line-height:22px;padding:0 8px 1px;font-size:11px}
16
 
17
+ #permalink-manager .woocommerce-icon:before{font-family:"WooCommerce";font-style:normal}
18
+ #permalink-manager .woocommerce-cart:before{content:"\e01d"}
19
+ #permalink-manager .woocommerce-logo:before{content:"\e03d"}
20
 
21
+ #permalink-manager .subsubsub{display:block;width:100%;overflow:hidden;margin-bottom:8px}
22
+ #permalink-manager .subsubsub li:before{content:" | "}
23
+ #permalink-manager .subsubsub li:first-child:before{content:"";color:#aaa}
24
+ #permalink-manager .subsubsub li .dashicons,#permalink-manager .subsubsub li .woocommerce-logo{font-size:100%;line-height:200%;height:auto;width:auto}
25
+ #permalink-manager .single-section{clear:both}
26
+ #permalink-manager .tablenav{margin:15px 0;height:auto}
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 .column-post_type,#permalink-manager .column-post_status,#permalink-manager .column-count,#permalink-manager .column-post_lang{width:13%}
31
+ #permalink-manager .column-count,#permalink-manager .column-post_lang,#permalink-manager th#count{text-align:center}
32
+ #permalink-manager th#count a{display:inline-block}
33
+ #permalink-manager .post_name input{max-width:100%}
34
+ #permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
35
+ #permalink-manager .post_permalink{margin-top:5px;display:block}
36
 
37
+ #permalink-manager .info{box-shadow:0 1px 1px 0 rgba(0,0,0,.1);display:block;overflow:hidden;clear:both;font-weight:bold;border-left:4px solid #dc3232;}
38
+ #permalink-manager .alert,#permalink-manager .info{line-height:19px;padding:11px 15px;margin:15px 0}
39
+ #permalink-manager .alert p,#permalink-manager .info p{margin-top:0;line-height:200%}
40
+ #permalink-manager .alert ul,#permalink-manager .alert ol{margin-top:0;margin-bottom:0}
41
+ #permalink-manager .alert p:last-of-type,#permalink-manager .alert li:last-of-type,#permalink-manager .info p:last-of-type{margin-bottom:0}
42
+ #permalink-manager .warning{background:#dc3232}
43
+ #permalink-manager .warning,#permalink-manager .warning a{color:#fff}
44
+ #permalink-manager .info{background:#f9f9f9}
45
+ #permalink-manager .section-notes,#permalink-manager .short-pre,#permalink-manager .short-textarea{padding:15px;font-size:13px;margin-top:15px;line-height:20px;background:#e5e5e5;border:1px solid #ccc;color:#555}
46
+ #permalink-manager .section-notes a,#permalink-manager .section-notes h3{color:#111}
47
+ #permalink-manager .section-notes h3,#permalink-manager .section-notes h4{margin-top:0}
48
+ #permalink-manager .section-notes h4{font-size:14px}
49
+ #permalink-manager .section-notes code{font-size:11px;background:#444;color:#fff}
50
+ #permalink-manager .section-notes ol{margin-top:0;margin-bottom:0}
51
+ #permalink-manager .section-notes ol li:last-of-type{margin-bottom:0}
52
+ #permalink-manager .short-pre,#permalink-manager .short-textarea{height:150px;overflow:auto;max-width:100%;display:block}
53
+ #permalink-manager .structure-tags-list{margin-top:15px}
54
 
55
+ #permalink-manager .checkbox_actions{padding-top:10px;border-top:1px solid #ddd}
56
+ #permalink-manager .extra-links,.permalink-manager-screen-options .extra-links{margin-top:5px;font-size:12px}
57
+ #permalink-manager .extra-links a,.permalink-manager-screen-options .extra-links a{color:#666;display:inline-block;text-decoration:none}
58
+ #permalink-manager .extra-links a:before,.permalink-manager-screen-options .extra-links a:before{content:" | "}
59
+ #permalink-manager .extra-links a:first-child:before,.permalink-manager-screen-options .extra-links a:first-child:before{content:""}
60
+ #permalink-manager .checkboxes{margin-left:-15px;margin-right:15px;overflow:hidden;display:block}
61
+ #permalink-manager .checkboxes > label{display:inline-block;width:33%;float:left;padding:0 15px;box-sizing:border-box;padding-bottom:5px}
62
+ #permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both}
63
+ #permalink-manager .field-description{font-size:12px}
64
+ #permalink-manager .appended-row td{padding-left:0;padding-right:0}
65
+ #permalink-manager #tools select{min-width:60%}
66
 
67
  /**
68
  * Columns
69
  */
70
+ #permalink-manager .columns-container{overflow:hidden;margin-left:-15px;margin-right:-15px;clear:both;display:block}
71
+ #permalink-manager .columns-container > *{float:left;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-box-sizing:border-box;overflow:hidden;display:block}
72
+ #permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-2_4{width:50%}
73
  #permalink-manager .columns-container .column-1_3{width:33.33%}
74
  #permalink-manager .columns-container .column-2_3{width:66.67%}
75
+ #permalink-manager .columns-container .column-1_4{width:25%}
76
+ #permalink-manager .columns-container .column-3_4{width:75%}
77
 
78
  #slugdiv #post_name{width:100%}
79
 
80
+ /**
81
+ * Edit URI box
82
+ */
83
+ #permalink-manager.permalink-manager-edit-uri-box{margin:10px -10px}
84
+ #permalink-manager.permalink-manager-edit-uri-box h2{border-bottom:1px solid #eee}
85
+ #permalink-manager.permalink-manager-edit-uri-box .inside{padding:0 10px 10px 10px}
86
+ #permalink-manager.permalink-manager-edit-uri-box .strong{display:block;font-weight:bold;margin-bottom:5px}
87
+ #permalink-manager.permalink-manager-edit-uri-box .toggle-indicator:before{content:"\f142";display:inline-block;font:400 20px/1 dashicons}
88
+ #permalink-manager.permalink-manager-edit-uri-box .default-permalink-row{color:#aaa;font-size:90%;border-top:1px solid #eee;padding-top:10px}
89
+ #permalink-manager.permalink-manager-edit-uri-box #restore-default-uri{display:block;text-align:center;width:100%;border-radius:0;color:#959595;text-decoration:none}
90
+ #permalink-manager.permalink-manager-edit-uri-box .columns-container{margin-left:-10px;margin-right:-10px}
91
+ #permalink-manager.permalink-manager-edit-uri-box .columns-container > *{padding-left:10px;padding-right:10px}
92
+ #permalink-manager.permalink-manager-edit-uri-box .close-button{float:right;width:36px;height:36px;padding:0;cursor:pointer;display:block}
93
+ #permalink-manager.permalink-manager-edit-uri-box .close-icon{margin-top:4px;-webkit-border-radius:50%;border-radius:50%;text-indent:-1px;color:#72777c;line-height:36px;display:block;text-align:center}
94
+ #permalink-manager.permalink-manager-edit-uri-box .close-icon:before{content:"\f158";display:inline-block;font:400 20px/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none!important}
95
+
96
+ /**
97
+ * Tippy.js custom theme
98
+ */
99
+ .tippy-tooltip.tippy-pm-theme{text-align:left;font-size:13px}
100
+
101
+ /**
102
+ * TagEditor custom theme & "Stop Words"
103
+ */
104
+ #permalink-manager .words-editor{font-size:90%;height:400px;overflow-y:auto;border:1px solid #ddd;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.07);box-shadow:inset 0 1px 2px rgba(0,0,0,.07);background-color:#fff;color:#32373c;outline:0;-webkit-transition:50ms border-color ease-in-out;transition:50ms border-color ease-in-out;}
105
+ #permalink-manager .words-editor .tag{background:#eee}
106
+ #permalink-manager .words-editor .tag a{color:#000}
107
+ #permalink-manager .stop-words-buttons{width:100%}
108
+ #permalink-manager .stop-words-buttons tr > td:first-child{padding-left:0;width:50%}
109
+ #permalink-manager .stop-words-buttons tr > td:last-child{padding-right:0}
110
+
111
  /**
112
  * Breakpoints
113
  */
114
+ @media only screen and (min-width :992px) {
115
+ #permalink-manager #permalink-manager-tab-nav .section_debug{float:right}
116
+ }
117
+ @media only screen and (max-width :782px) {
118
  #permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-1_3,#permalink-manager .columns-container .column-2_3{width:100%}
119
  }
out/permalink-manager-admin.js CHANGED
@@ -1,12 +1,12 @@
1
  jQuery(document).ready(function() {
2
 
3
- /*
4
  * "(Un)select all" checkboxes
5
  */
6
  var checkbox_actions = ['select_all', 'unselect_all'];
7
  checkbox_actions.forEach(function(element) {
8
  jQuery('.' + element).on('click', function() {
9
- jQuery(this).parents('td').find('.checkboxes input[type="checkbox"]').each(function() {
10
  var action = (element == 'select_all') ? true : false;
11
  jQuery(this).prop('checked', action);
12
  });
@@ -22,4 +22,143 @@ jQuery(document).ready(function() {
22
  }
23
  });
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  });
1
  jQuery(document).ready(function() {
2
 
3
+ /**
4
  * "(Un)select all" checkboxes
5
  */
6
  var checkbox_actions = ['select_all', 'unselect_all'];
7
  checkbox_actions.forEach(function(element) {
8
  jQuery('.' + element).on('click', function() {
9
+ jQuery(this).parents('.field-container').find('.checkboxes input[type="checkbox"]').each(function() {
10
  var action = (element == 'select_all') ? true : false;
11
  jQuery(this).prop('checked', action);
12
  });
22
  }
23
  });
24
 
25
+ /**
26
+ * Filter by dates in "Permalink editor"
27
+ */
28
+ jQuery('#months-filter-button').on('click', function() {
29
+ var filter_name = jQuery("#months-filter-select").attr('name');
30
+ var filter_value = jQuery("#months-filter-select").val();
31
+ var url = jQuery(this).parent().data('filter-url');
32
+
33
+ if(filter_name != '' && filter_value != '' && url != ''){
34
+ document.location.href = url + "&" + filter_name + "=" + filter_value;
35
+ }
36
+ return false;
37
+ });
38
+
39
+ /**
40
+ * Filter by content types in "Tools"
41
+ */
42
+ jQuery('*[data-field="content_type"] select').on('change', function() {
43
+ var content_type = jQuery(this).val();
44
+ if(content_type == 'post_types') {
45
+ jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').removeClass('hidden');
46
+ jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').addClass('hidden');
47
+ } else {
48
+ jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').addClass('hidden');
49
+ jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').removeClass('hidden');
50
+ }
51
+ }).trigger("change");
52
+
53
+ /**
54
+ * Toggle "Edit URI" box
55
+ */
56
+ jQuery('#permalink-manager-toggle, .permalink-manager-edit-uri-box .close-button').on('click', function() {
57
+ jQuery('.permalink-manager-edit-uri-box').slideToggle();
58
+
59
+ return false;
60
+ }).trigger('keyup');
61
+
62
+ /**
63
+ * Synchronize "Edit URI" input field with the sample permalink
64
+ */
65
+ var custom_uri_input = jQuery('.permalink-manager-edit-uri-box input[name="custom_uri"]');
66
+ jQuery(custom_uri_input).on('keyup change', function() {
67
+ jQuery('.sample-permalink-span .editable').text(jQuery(this).val());
68
+ });
69
+
70
+ /**
71
+ * Disable "Edit URI" input if URI should be updated automatically
72
+ */
73
+ jQuery('.permalink-manager-edit-uri-box select[name="auto_update_uri"]').on('change', function() {
74
+ var selected = jQuery(this).find('option:selected');
75
+ var auto_update_status = jQuery(selected).data('auto-update');
76
+
77
+ if(auto_update_status == 1) {
78
+ jQuery(custom_uri_input).attr("disabled", true);
79
+ } else {
80
+ jQuery(custom_uri_input).removeAttr("disabled", true);
81
+ }
82
+ }).trigger("change");
83
+
84
+ /**
85
+ * Restore "Default URI"
86
+ */
87
+ jQuery('#restore-default-uri').on('click', function() {
88
+ jQuery('input[data-default-uri]').each(function() {
89
+ jQuery(this).val(jQuery(this).data('default-uri')).trigger('keyup');
90
+ });
91
+ return false;
92
+ });
93
+
94
+ /**
95
+ * Hide global admin notices
96
+ */
97
+ jQuery(document).on('click', '.permalink-manager-notice.is-dismissible .notice-dismiss', function() {
98
+ var alert_id = jQuery(this).closest('.permalink-manager-notice').data('alert_id');
99
+
100
+ jQuery.ajax(ajaxurl, {
101
+ type: 'POST',
102
+ data: {
103
+ action: 'dismissed_notice_handler',
104
+ alert_id: alert_id,
105
+ }
106
+ });
107
+ });
108
+
109
+ /**
110
+ * Help tooltips
111
+ */
112
+ new Tippy('.help_tooltip', {
113
+ position: 'top-start',
114
+ arrow: true,
115
+ theme: 'tippy-pm',
116
+ distance: 20,
117
+ });
118
+
119
+ /**
120
+ * Stop-words
121
+ */
122
+ var stop_words_input = '.field-container textarea.stop_words';
123
+
124
+ if(jQuery(stop_words_input).length > 0) {
125
+ var stop_words = new TIB(document.querySelector(stop_words_input), {
126
+ alert: false,
127
+ escape: null,
128
+ classes: ['tags words-editor', 'tag', 'tags-input', 'tags-output', 'tags-view'],
129
+ });
130
+ jQuery('.tags-output').hide();
131
+
132
+ // Force lowercase
133
+ stop_words.filter = function(text) {
134
+ return text.toLowerCase();
135
+ };
136
+
137
+ // Remove all words
138
+ jQuery('.field-container .clear_all_words').on('click', function() {
139
+ stop_words.reset();
140
+ });
141
+
142
+ // Load stop-words list
143
+ jQuery('#load_stop_words_button').on('click', function() {
144
+ var lang = jQuery( ".load_stop_words option:selected" ).val();
145
+ if(lang) {
146
+ var json_url = permalink_manager.url + "/includes/ext/stopwords-json/dist/" + lang + ".json";
147
+
148
+ // Load JSON with words list
149
+ jQuery.getJSON(json_url, function(data) {
150
+ var new_words = [];
151
+
152
+ jQuery.each(data, function(key, val) {
153
+ new_words.push(val);
154
+ });
155
+
156
+ stop_words.update(new_words);
157
+ });
158
+ }
159
+
160
+ return false;
161
+ });
162
+ }
163
+
164
  });
out/permalink-manager-plugins.css ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**!
2
+ * tippy.js (v.0.15.0)
3
+ * https://atomiks.github.io/tippyjs/
4
+ * Copyright (c) 2017 atomiks (Tippy) & FezVrasta (Popper)
5
+ * @file tippy.js (popper.js 1.9.9 included) | Pure JS Tooltip Library
6
+ * @license MIT
7
+ */
8
+ .tippy-touch{cursor:pointer!important}.tippy-notransition{-webkit-transition:none!important;transition:none!important}.tippy-popper{max-width:400px;-webkit-perspective:800px;perspective:800px;z-index:9999}.tippy-popper.html-template{max-width:96%;max-width:calc(100% - 20px)}.tippy-popper[x-placement^=top] [x-arrow]{position:absolute;width:0;height:0;border-top:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;bottom:-7px}.tippy-popper[x-placement^=top] [x-arrow].arrow-small{border-top:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;bottom:-5px}.tippy-popper[x-placement^=top] [x-arrow].arrow-big{border-top:9px solid #333;border-right:9px solid transparent;border-left:9px solid transparent;bottom:-9px}.tippy-popper[x-placement^=top] [x-circle]{-webkit-transform-origin:0 100%;transform-origin:0 100%}.tippy-popper[x-placement^=top] [x-circle].enter{opacity:1;-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=top] [x-circle].leave{opacity:0;-webkit-transform:scale(.45) translate(-50%,-100%);transform:scale(.45) translate(-50%,-100%)}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow]{border-top:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-top:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-top:9px solid #fff;border-right:9px solid transparent;border-left:9px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow]{border-top:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-top:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-top:9px solid rgba(0,0,0,.7);border-right:9px solid transparent;border-left:9px solid transparent}.tippy-popper[x-placement^=top] [data-animation=perspective]{-webkit-transform-origin:bottom;transform-origin:bottom}.tippy-popper[x-placement^=top] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(-10px) rotateX(0);transform:translateY(-10px) rotateX(0)}.tippy-popper[x-placement^=top] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(90deg);transform:translateY(0) rotateX(90deg)}.tippy-popper[x-placement^=top] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=top] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(-10px) scale(1);transform:translateY(-10px) scale(1)}.tippy-popper[x-placement^=top] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=bottom] [x-arrow]{position:absolute;width:0;height:0;border-bottom:7px solid #333;border-right:7px solid transparent;border-left:7px solid transparent;top:-7px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-small{border-bottom:5px solid #333;border-right:5px solid transparent;border-left:5px solid transparent;top:-5px}.tippy-popper[x-placement^=bottom] [x-arrow].arrow-big{border-bottom:9px solid #333;border-right:9px solid transparent;border-left:9px solid transparent;top:-9px}.tippy-popper[x-placement^=bottom] [x-circle]{-webkit-transform-origin:0 -100%;transform-origin:0 -100%}.tippy-popper[x-placement^=bottom] [x-circle].enter{opacity:1;-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=bottom] [x-circle].leave{opacity:0;-webkit-transform:scale(.45) translate(-50%,5%);transform:scale(.45) translate(-50%,5%)}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow]{border-bottom:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-bottom:5px solid #fff;border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-bottom:9px solid #fff;border-right:9px solid transparent;border-left:9px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow]{border-bottom:7px solid rgba(0,0,0,.7);border-right:7px solid transparent;border-left:7px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-bottom:5px solid rgba(0,0,0,.7);border-right:5px solid transparent;border-left:5px solid transparent}.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-bottom:9px solid rgba(0,0,0,.7);border-right:9px solid transparent;border-left:9px solid transparent}.tippy-popper[x-placement^=bottom] [data-animation=perspective]{-webkit-transform-origin:top;transform-origin:top}.tippy-popper[x-placement^=bottom] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateY(10px) rotateX(0);transform:translateY(10px) rotateX(0)}.tippy-popper[x-placement^=bottom] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateY(0) rotateX(-90deg);transform:translateY(0) rotateX(-90deg)}.tippy-popper[x-placement^=bottom] [data-animation=fade].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=fade].leave{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].enter{opacity:1;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift].leave{opacity:0;-webkit-transform:translateY(0);transform:translateY(0)}.tippy-popper[x-placement^=bottom] [data-animation=scale].enter{opacity:1;-webkit-transform:translateY(10px) scale(1);transform:translateY(10px) scale(1)}.tippy-popper[x-placement^=bottom] [data-animation=scale].leave{opacity:0;-webkit-transform:translateY(0) scale(0);transform:translateY(0) scale(0)}.tippy-popper[x-placement^=left] [x-arrow]{position:absolute;width:0;height:0;border-left:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;right:-7px;top:50%}.tippy-popper[x-placement^=left] [x-arrow].arrow-small{border-left:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;right:-5px;top:50%}.tippy-popper[x-placement^=left] [x-arrow].arrow-big{border-left:9px solid #333;border-top:9px solid transparent;border-bottom:9px solid transparent;right:-9px;top:50%}.tippy-popper[x-placement^=left] [x-circle]{-webkit-transform-origin:50% 0;transform-origin:50% 0}.tippy-popper[x-placement^=left] [x-circle].enter{opacity:1;-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=left] [x-circle].leave{opacity:0;-webkit-transform:scale(.45) translate(-50%,-50%);transform:scale(.45) translate(-50%,-50%)}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow]{border-left:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-left:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-left:9px solid #fff;border-top:9px solid transparent;border-bottom:9px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow]{border-left:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-left:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-left:9px solid rgba(0,0,0,.7);border-top:9px solid transparent;border-bottom:9px solid transparent}.tippy-popper[x-placement^=left] [data-animation=perspective]{-webkit-transform-origin:right;transform-origin:right}.tippy-popper[x-placement^=left] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(-10px) rotateY(0);transform:translateX(-10px) rotateY(0)}.tippy-popper[x-placement^=left] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(-90deg);transform:translateX(0) rotateY(-90deg)}.tippy-popper[x-placement^=left] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=left] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(-10px) scale(1);transform:translateX(-10px) scale(1)}.tippy-popper[x-placement^=left] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper[x-placement^=right] [x-arrow]{position:absolute;width:0;height:0;border-right:7px solid #333;border-top:7px solid transparent;border-bottom:7px solid transparent;left:-7px;top:50%}.tippy-popper[x-placement^=right] [x-arrow].arrow-small{border-right:5px solid #333;border-top:5px solid transparent;border-bottom:5px solid transparent;left:-5px;top:50%}.tippy-popper[x-placement^=right] [x-arrow].arrow-big{border-right:9px solid #333;border-top:9px solid transparent;border-bottom:9px solid transparent;left:-9px;top:50%}.tippy-popper[x-placement^=right] [x-circle]{-webkit-transform-origin:-50% 0;transform-origin:-50% 0}.tippy-popper[x-placement^=right] [x-circle].enter{opacity:1;-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=right] [x-circle].leave{opacity:0;-webkit-transform:scale(.45) translate(-50%,-50%);transform:scale(.45) translate(-50%,-50%)}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-circle]{background-color:#fff}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow]{border-right:7px solid #fff;border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-small{border-right:5px solid #fff;border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.light-theme [x-arrow].arrow-big{border-right:9px solid #fff;border-top:9px solid transparent;border-bottom:9px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-circle]{background-color:rgba(0,0,0,.7)}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow]{border-right:7px solid rgba(0,0,0,.7);border-top:7px solid transparent;border-bottom:7px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-small{border-right:5px solid rgba(0,0,0,.7);border-top:5px solid transparent;border-bottom:5px solid transparent}.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-big{border-right:9px solid rgba(0,0,0,.7);border-top:9px solid transparent;border-bottom:9px solid transparent}.tippy-popper[x-placement^=right] [data-animation=perspective]{-webkit-transform-origin:left;transform-origin:left}.tippy-popper[x-placement^=right] [data-animation=perspective].enter{opacity:1;-webkit-transform:translateX(10px) rotateY(0);transform:translateX(10px) rotateY(0)}.tippy-popper[x-placement^=right] [data-animation=perspective].leave{opacity:0;-webkit-transform:translateX(0) rotateY(90deg);transform:translateX(0) rotateY(90deg)}.tippy-popper[x-placement^=right] [data-animation=fade].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=fade].leave{opacity:0;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].enter{opacity:1;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift].leave{opacity:0;-webkit-transform:translateX(0);transform:translateX(0)}.tippy-popper[x-placement^=right] [data-animation=scale].enter{opacity:1;-webkit-transform:translateX(10px) scale(1);transform:translateX(10px) scale(1)}.tippy-popper[x-placement^=right] [data-animation=scale].leave{opacity:0;-webkit-transform:translateX(0) scale(0);transform:translateX(0) scale(0)}.tippy-popper [x-circle]{background-color:#fff}.tippy-popper[data-animatefill]{background-color:transparent}.tippy-popper [x-arrow]{position:absolute;width:0;height:0}.tippy-popper .tippy-tooltip.transparent-theme{background-color:rgba(0,0,0,.7)}.tippy-popper .tippy-tooltip.transparent-theme[data-animatefill]{background-color:transparent}.tippy-popper .tippy-tooltip.light-theme{color:#203d5d;box-shadow:0 4px 20px 4px rgba(0,20,60,.1),0 4px 80px -8px rgba(0,20,60,.2);background-color:#fff}.tippy-popper .tippy-tooltip.light-theme[data-animatefill]{background-color:transparent}.tippy-tooltip{position:relative;color:#fff;border-radius:4px;font-size:.95rem;padding:.4rem .8rem;text-align:center;will-change:transform;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#333}.tippy-tooltip--small{padding:.25rem .5rem;font-size:.8rem}.tippy-tooltip--big{padding:.6rem 1.2rem;font-size:1.2rem}.tippy-tooltip[data-animatefill]{overflow:hidden;background-color:transparent}.tippy-tooltip[data-inertia]{-webkit-transition-timing-function:cubic-bezier(.53,1,.36,.85);transition-timing-function:cubic-bezier(.53,2,.36,.85)}.tippy-tooltip [x-circle]{position:absolute;will-change:transform;background-color:#333;border-radius:50%;width:120%;width:calc(100% + 2rem);-webkit-transition:all ease-out;transition:all ease-out;left:50%;top:50%;z-index:-1;opacity:0;overflow:hidden}.tippy-tooltip [x-circle]:before{content:"";padding-top:75%;float:left}@media (max-width:450px){.tippy-popper{max-width:96%;max-width:calc(100% - 20px)}}
9
+
10
+ /**
11
+ * Simplest Tags Input Beautifier
12
+ * Copyright (c) Taufik Nurrohman
13
+ * https://github.com/tovic
14
+ * @license MIT
15
+ * @version 2.1.3
16
+ */
17
+ .words-editor{font:inherit;font-weight:400;font-style:normal;color:#000;border:1px solid;display:block;line-height:1.25;padding:.25em 0 0 .25em;cursor:text;overflow:hidden}.words-editor span{display:block;float:left;position:relative}.words-editor .tag,.words-editor-input{background:red;margin:0 .25em .25em 0;padding:.25em .5em;min-height:1.25em;cursor:default}.words-editor .tag:before{content:attr(data-tag)}.words-editor-view:after,.words-editor:after{content:"";display:table;clear:both}.words-editor a{display:inline-block;margin:0 0 0 .5em;color:#fff;text-decoration:none;cursor:pointer}.words-editor .tag+.words-editor-input span+span,.words-editor-output{display:none}.words-editor a:before{content:'\00D7'}.words-editor .words-editor-view{float:none}.words-editor .words-editor-input{float:none;background:0 0;cursor:inherit;min-width:1em}.words-editor-input span{float:none;position:absolute;top:0;right:0;bottom:0;left:0;z-index:4;padding:inherit}.words-editor-input span+span{position:static;padding:0;opacity:.5}.words-editor .tag+.words-editor-input{float:left}.words-editor-input span:focus+span{opacity:.4}
out/permalink-manager-plugins.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**!
2
+ * tippy.js (v.0.15.0)
3
+ * https://atomiks.github.io/tippyjs/
4
+ * Copyright (c) 2017 atomiks (Tippy) & FezVrasta (Popper)
5
+ * @file tippy.js (popper.js 1.9.9 included) | Pure JS Tooltip Library
6
+ * @license MIT
7
+ */
8
+ !function(t){function e(n){if(i[n])return i[n].exports;var o=i[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var i={};e.m=t,e.c=i,e.i=function(t){return t},e.d=function(t,i,n){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=4)}([function(t,e,i){"use strict";i(2),i(1)},function(t,e,i){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var o=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},r=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}(),s=i(3),a=function(t){return t&&t.__esModule?t:{default:t}}(s),l=function(){function t(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(n(this,t),"addEventListener"in window&&!/MSIE 9/i.test(navigator.userAgent)&&!window.operamini){if(this.defaultSettings={html:!1,position:"top",animation:"shift",animateFill:!0,arrow:!1,delay:0,hideDelay:0,trigger:"mouseenter focus",duration:400,hideDuration:400,interactive:!1,theme:"dark",offset:0,hideOnClick:!0,multiple:!1,followCursor:!1,inertia:!1,popperOptions:{}},this.settings=this._applyGlobalSettings(i),this.classNames={popper:"tippy-popper",tooltip:"tippy-tooltip",content:"tippy-tooltip-content"},this.tooltippedEls=e instanceof Element?[e]:[].slice.call(document.querySelectorAll(e)),t.bus||(t.bus={refs:[],tooltippedEls:[],poppers:[],listeners:{}}),!t.bus.listeners.touchstart){t.bus.listeners.touchstart=!0;var o=function e(){t.touchUser=!0,document.body.classList.add("tippy-touch"),window.removeEventListener("touchstart",e)};window.addEventListener("touchstart",o)}this._createTooltips(),t.bus.listeners.click||this._handleDocumentClick()}}return r(t,[{key:"_closest",value:function(t,e){if(!Element.prototype.matches)if(t.matchesSelector)Element.prototype.matches=Element.prototype.matchesSelector;else if(t.webkitMatchesSelector)Element.prototype.matches=Element.prototype.webkitMatchesSelector;else if(t.mozMatchesSelector)Element.prototype.matches=Element.prototype.mozMatchesSelector;else{if(!t.msMatchesSelector)return t;Element.prototype.matches=Element.prototype.msMatchesSelector}return Element.prototype.closest||(Element.prototype.closest=function(t){for(var e=this;e;){if(e.matches(t))return e;e=e.parentElement}}),t.closest(e)}},{key:"_applyGlobalSettings",value:function(t){return"function"!=typeof Object.assign&&(Object.assign=function(t,e){for(var i=Object(t),n=1;n<arguments.length;n++){var o=arguments[n];if(null!=o)for(var r in o)Object.prototype.hasOwnProperty.call(o,r)&&(i[r]=o[r])}return i}),this.callbacks={beforeShown:t.beforeShown||new Function,shown:t.shown||new Function,beforeHidden:t.beforeHidden||new Function,hidden:t.hidden||new Function},Object.assign(this.defaultSettings,t)}},{key:"_hideAllPoppers",value:function(){var e=this,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;t.bus.refs.forEach(function(t){document.body.contains(t.popper)&&(i?t.popper!==i.popper&&e.hide(t.popper):e.hide(t.popper))})}},{key:"_handleDocumentClick",value:function(){var e=this,i=function(t){var i=e._closest(t,"[data-tooltipped]"),n=e._closest(t,"."+e.classNames.popper),o={};return i?(o.type="tooltippedEl",o.target=i):n?(o.type="popper",o.target=n):o=null,o},n=function(e){var n=-1,o=-1,r=i(e);return r&&("tooltippedEl"===r.type?n=t.bus.tooltippedEls.indexOf(r.target):"popper"===r.type&&(o=t.bus.poppers.indexOf(r.target))),{tooltippedElIndex:n,popperIndex:o}},o=function(i){var o=n(i.target),r=o.tooltippedElIndex!==-1;if(o.popperIndex!==-1&&t.bus.refs[o.popperIndex].settings.interactive)return;if(r){var s=t.bus.refs[o.tooltippedElIndex];if(!s.settings.multiple&&(s.settings.trigger.indexOf("click")!==-1||t.touchUser))return void e._hideAllPoppers(s);if(!s.settings.hideOnClick||s.settings.trigger.indexOf("click")!==-1)return}e._hideAllPoppers()};t.bus.listeners.click=o,document.addEventListener("click",o)}},{key:"_createPopperInstance",value:function(t,e,i){var n=o({placement:i.position},i.popperOptions||{},{modifiers:o({},i.popperOptions?i.popperOptions.modifiers:{},{offset:o({offset:parseInt(i.offset)},i.popperOptions&&i.popperOptions.modifiers?i.popperOptions.modifiers.offset:{})})});document.body.appendChild(e);var r=new a.default(t,e,n);return r.disableEventListeners(),document.body.removeChild(e),r}},{key:"_createPopperElement",value:function(t,e){var i=document.createElement("div");i.setAttribute("class",this.classNames.popper);var n=document.createElement("div");if(n.setAttribute("class",this.classNames.tooltip+" "+e.theme+" leave"),n.setAttribute("data-animation",e.animation),e.arrow){var o=document.createElement("div");o.setAttribute("x-arrow",""),n.appendChild(o)}if(e.animateFill){n.setAttribute("data-animatefill","");var r=document.createElement("div");r.setAttribute("class","leave"),r.setAttribute("x-circle",""),n.appendChild(r)}e.inertia&&n.setAttribute("data-inertia","");var s=document.createElement("div");return s.setAttribute("class",this.classNames.content),e.html?(s.innerHTML=document.getElementById(e.html.replace("#","")).innerHTML,i.classList.add("html-template"),i.setAttribute("tabindex","0"),n.setAttribute("data-template-id",e.html)):s.innerHTML=t,n.appendChild(s),i.appendChild(n),i}},{key:"_applyIndividualSettings",value:function(t){var e=t.getAttribute("data-html")||this.settings.html;e&&"false"!==e||(e=!1);var i=t.getAttribute("data-position")||this.settings.position,n=t.getAttribute("data-animation")||this.settings.animation,o=t.getAttribute("data-animatefill")||this.settings.animateFill;"false"===o&&(o=!1);var r=t.getAttribute("data-arrow")||this.settings.arrow;r&&"false"!==r?o=!1:r=!1;var s=t.getAttribute("data-trigger")||this.settings.trigger;s&&(s=s.trim().split(" "));var a=t.getAttribute("data-theme")||this.settings.theme;a&&(a+="-theme");var l=parseInt(t.getAttribute("data-delay"));l||0===l||(l=this.settings.delay);var p=parseInt(t.getAttribute("data-hidedelay"));p||0===p||(p=this.settings.hideDelay);var f=parseInt(t.getAttribute("data-duration"));f||0===f||(f=this.settings.duration);var u=parseInt(t.getAttribute("data-hideduration"));u||0===u||(u=this.settings.hideDuration);var d=t.getAttribute("data-interactive")||this.settings.interactive;"false"===d&&(d=!1);var c=parseInt(t.getAttribute("data-offset"));c||0===c||(c=this.settings.offset);var h=t.getAttribute("data-hideonclick")||this.settings.hideOnClick;"false"===h&&(h=!1);var m=t.getAttribute("data-multiple")||this.settings.multiple;"false"===m&&(m=!1);var v=t.getAttribute("data-followcursor")||this.settings.followCursor;"false"===v&&(v=!1);var g=t.getAttribute("data-inertia")||this.settings.inertia;return"false"===g&&(g=!1),{html:e,position:i,animation:n,animateFill:o,arrow:r,delay:l,hideDelay:p,trigger:s,duration:f,hideDuration:u,interactive:d,theme:a,offset:c,hideOnClick:h,multiple:m,followCursor:v,inertia:g,popperOptions:this.settings.popperOptions}}},{key:"_getEventListenerMethods",value:function(e,i,n){var o=this,r=function(){if(n.delay){var t=setTimeout(function(){return o.show(i,n.duration)},n.delay);i.setAttribute("data-delay",t)}else o.show(i,n.duration)},s=function(){if(n.hideDelay){var t=setTimeout(function(){return o.hide(i,n.hideDuration)},n.hideDelay);i.setAttribute("data-hidedelay",t)}else o.hide(i,n.hideDuration)};return{handleTrigger:function(t){if(n.interactive&&t.target.classList.add("active"),"click"===t.type&&"visible"===i.style.visibility&&n.hideOnClick)return s();r()},handleMouseleave:function(t){if(n.interactive){var r=function t(r){o._closest(r.target,"."+o.classNames.popper)!==i&&o._closest(r.target,"[data-tooltipped]")!==e&&n.trigger.indexOf("click")===-1&&(document.removeEventListener("mousemove",t),e.classList.remove("active"),s())};return void document.addEventListener("mousemove",r)}s()},handleBlur:function(e){!t.touchUser&&e.relatedTarget&&(o._closest(e.relatedTarget,"."+o.classNames.popper)||s())}}}},{key:"_createTrigger",value:function(t,e,i,n){if("manual"!==t)return e.addEventListener(t,i.handleTrigger),n.push({event:t,method:i.handleTrigger}),"mouseenter"===t&&(e.addEventListener("mouseleave",i.handleMouseleave),n.push({event:"mouseleave",method:i.handleMouseleave})),"focus"===t&&(e.addEventListener("blur",i.handleBlur),n.push({event:"blur",method:i.handleBlur})),n}},{key:"_pushIntoTippyBus",value:function(e){t.bus.refs.push(e),t.bus.tooltippedEls.push(e.tooltippedEl),t.bus.poppers.push(e.popper)}},{key:"_createTooltips",value:function(){var t=this;this.tooltippedEls.forEach(function(e){var i=t._applyIndividualSettings(e),n=e.getAttribute("title");if(null!==n&&""!==n||i.html){e.setAttribute("data-tooltipped",""),e.setAttribute("data-original-title",n||"html"),e.removeAttribute("title");var o=t._createPopperElement(n,i),r=t._createPopperInstance(e,o,i),s=t._getEventListenerMethods(e,o,i),a=[];i.trigger.forEach(function(i){a=t._createTrigger(i,e,s,a)}),t._pushIntoTippyBus({tooltippedEl:e,popper:o,settings:i,listeners:a,instance:r})}})}},{key:"_followCursor",value:function(e){var i=t.bus.refs[t.bus.tooltippedEls.indexOf(this)],n=i.settings.position,o=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop,r=Math.round(i.popper.offsetWidth/2),s=Math.round(i.popper.offsetHeight/2),a=e.clientX-r,l=e.clientY+o-50;"left"===n?(a=e.clientX-2*r-10,l=e.clientY+o-s):"right"===n?(a=e.clientX+15,l=e.clientY+o-s):"bottom"===n&&(l=e.clientY+o+15),i.popper.style.WebkitTransform="translate3d("+a+"px, "+l+"px, 0)",i.popper.style.transform="translate3d("+a+"px, "+l+"px, 0)"}},{key:"getPopperElement",value:function(e){try{return t.bus.refs[t.bus.tooltippedEls.indexOf(e)].popper}catch(t){throw new Error("[Tippy error]: Element does not exist in any Tippy instances")}}},{key:"show",value:function(e){var i=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.defaultSettings.duration;if(clearTimeout(e.getAttribute("data-hidedelay")),"visible"!==e.style.visibility){this.callbacks.beforeShown(),e.style.visibility="visible";var o=t.bus.refs[t.bus.poppers.indexOf(e)],r=e.querySelector("."+this.classNames.tooltip),s=e.querySelector("[x-circle]"),a=e.querySelector("[x-arrow]");if(document.body.appendChild(e),o.settings.followCursor&&!t.touchUser?o.hasFollowCursorListener||(o.hasFollowCursorListener=!0,o.tooltippedEl.addEventListener("mousemove",this._followCursor)):(o.instance.update(),o.instance.enableEventListeners()),getComputedStyle(e).opacity,getComputedStyle(r).opacity,a&&getComputedStyle(a).opacity,r.style.WebkitTransitionDuration=n+"ms",r.style.transitionDuration=n+"ms",r.classList.add("enter"),r.classList.remove("leave"),s){var l=getComputedStyle(s);l.WebkitTransformOrigin,l.transformOrigin,s.style.WebkitTransitionDuration=n+"ms",s.style.transitionDuration=n+"ms",s.classList.add("enter"),s.classList.remove("leave")}var p=function(){"hidden"!==e.style.visibility&&(o.settings.trigger.indexOf("click")!==-1&&e.focus(),i.callbacks.shown())};clearTimeout(o.showTimeout),o.showTimeout=setTimeout(p,n)}}},{key:"hide",value:function(e){var i=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.settings.hideDuration;if(clearTimeout(e.getAttribute("data-delay")),document.body.contains(e)){this.callbacks.beforeHidden(),e.style.visibility="hidden";var o=t.bus.refs[t.bus.poppers.indexOf(e)],r=e.querySelector("."+this.classNames.tooltip),s=e.querySelector("[x-circle]");o.tooltippedEl.classList.remove("active"),r.classList.add("leave"),r.classList.remove("enter"),s&&(s.classList.add("leave"),s.classList.remove("enter")),n===this.defaultSettings.hideDuration?r.style.transitionDuration?n=parseInt(r.style.transitionDuration.replace("ms","")):r.style.WebkitTransitionDuration&&(n=parseInt(r.style.WebkitTransitionDuration.replace("ms",""))):(r.style.WebkitTransitionDuration=n+"ms",r.style.transitionDuration=n+"ms",s&&(s.style.WebkitTransitionDuration=n+"ms",s.style.transitionDuration=n+"ms")),o.settings.html&&o.settings.trigger.indexOf("click")!==-1&&o.tooltippedEl.focus();var a=function(){"visible"!==e.style.visibility&&(o.hasFollowCursorListener&&(o.tooltippedEl.removeEventListener("mousemove",i._followCursor),o.hasFollowCursorListener=!1),document.body.contains(e)&&document.body.removeChild(e),o.instance.disableEventListeners(),i.callbacks.hidden())};clearTimeout(o.hideTimeout),o.hideTimeout=setTimeout(a,n)}}},{key:"destroy",value:function(e){var i=t.bus.poppers.indexOf(e),n=t.bus.refs[i];n.listeners.forEach(function(t){return n.tooltippedEl.removeEventListener(t.event,t.method)}),n.instance.destroy(),t.bus.poppers.splice(i,1),t.bus.tooltippedEls.splice(i,1),t.bus.refs.splice(i,1)}}]),t}();window.Tippy=l,t.exports=l},function(t,e){},function(t,e,i){
9
+ !function(e,i){t.exports=i()}(0,function(){"use strict";function t(t){var e=t.offsetParent,i=e&&e.nodeName;return i&&"BODY"!==i&&"HTML"!==i?e:window.document.documentElement}function e(t,e){if(1!==t.nodeType)return[];var i=window.getComputedStyle(t,null);return e?i[e]:i}function i(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function n(t){if(!t||["HTML","BODY","#document"].indexOf(t.nodeName)!==-1)return window.document.body;var o=e(t),r=o.overflow,s=o.overflowX,a=o.overflowY;return/(auto|scroll)/.test(r+a+s)?t:n(i(t))}function o(t){var n=t.nodeName;return"BODY"!==n&&"HTML"!==n&&("fixed"===e(t,"position")||o(i(t)))}function r(e){return o(t(e))?"fixed":"absolute"}function s(t,e){var i="x"===e?"Left":"Top",n="Left"===i?"Right":"Bottom";return Number(t["border"+i+"Width"].split("px")[0])+Number(t["border"+n+"Width"].split("px")[0])}function a(t){var i=navigator.appVersion.indexOf("MSIE 10")!==-1,n=void 0;if(i)try{n=t.getBoundingClientRect()}catch(t){n={}}else n=t.getBoundingClientRect();var o={left:n.left,top:n.top,right:n.right,bottom:n.bottom,width:n.right-n.left,height:n.bottom-n.top};if("HTML"===t.nodeName&&i){var r=window.document.documentElement,a=r.scrollTop,l=r.scrollLeft;o.top-=a,o.bottom-=a,o.left-=l,o.right-=l}var p=n.width-(t.clientWidth||n.right-n.left),f=n.height-(t.clientHeight||n.bottom-n.top);if(p||f){var u=e(t);p-=s(u,"x"),f-=s(u,"y")}return o.right-=p,o.width-=p,o.bottom-=f,o.height-=f,o}function l(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",i="top"===e?"scrollTop":"scrollLeft",n=t.nodeName;if("BODY"===n||"HTML"===n){var o=window.document.documentElement;return(window.document.scrollingElement||o)[i]}return t[i]}function p(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=l(e,"top"),o=l(e,"left"),r=i?-1:1;return t.top+=n*r,t.bottom+=n*r,t.left+=o*r,t.right+=o*r,t}function f(i,o){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],l=n(o),f=a(i),u=a(o),d={top:f.top-u.top,left:f.left-u.left,bottom:f.top-u.top+f.height,right:f.left-u.left+f.width,width:f.width,height:f.height};r&&!s?d=p(d,l,!0):t(i).contains(l)&&"BODY"!==l.nodeName&&(d=p(d,o));var c=e(o),h=Number(c.borderTopWidth.split("px")[0]),m=Number(c.borderLeftWidth.split("px")[0]);return d.top-=h,d.bottom-=h,d.left-=m,d.right-=m,d}function u(){var t=window.document.body,e=window.document.documentElement;return{height:Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight),width:Math.max(t.scrollWidth,t.offsetWidth,e.clientWidth,e.scrollWidth,e.offsetWidth)}}function d(t){var e=void 0;if("HTML"===t.nodeName){var i=u();e={width:i.width,height:i.height,left:0,top:0}}else e={width:t.offsetWidth,height:t.offsetHeight,left:t.offsetLeft,top:t.offsetTop};return e.right=e.left+e.width,e.bottom=e.top+e.height,e}function c(e){var i=d(e);if("HTML"!==e.nodeName){var n=t(e),o=c(n);return{width:i.offsetWidth,height:i.offsetHeight,left:i.left+o.left,top:i.top+o.top,right:i.right-o.right,bottom:i.bottom-o.bottom}}return i}function h(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",o=n(t),r=l(o,e);return["BODY","HTML"].indexOf(o.nodeName)===-1?r+h(i(o),e):r}function m(e,s,a){var l={top:0,left:0},p=t(e);if("viewport"===a){var d=c(p),m=d.left,v=d.top,g=window.document.documentElement,b=g.clientWidth,y=g.clientHeight;if("fixed"===r(e))l.right=b,l.bottom=y;else{l={top:0-v,right:b-m+h(e,"left"),bottom:y-v+h(e,"top"),left:0-m}}}else{var w=void 0;if(w="scrollParent"===a?n(i(e)):"window"===a?window.document.body:a,"BODY"===w.nodeName){var E=u(),O=E.height,x=E.width;l.right=x,l.bottom=O}else l=f(w,p,o(e))}return l.left+=s,l.top+=s,l.right-=s,l.bottom-=s,l}function v(t,e,i){if(t.indexOf("auto")===-1)return t;var n=m(i,0,"scrollParent"),o={top:e.top-n.top,right:n.right-e.right,bottom:n.bottom-e.bottom,left:e.left-n.left},r=Object.keys(o).sort(function(t,e){return o[e]-o[t]})[0],s=t.split("-")[1];return r+(s?"-"+s:"")}function g(t){var e=!1,i=0,n=document.createElement("span");return new MutationObserver(function(){t(),e=!1}).observe(n,{attributes:!0}),function(){e||(e=!0,n.setAttribute("x-index",i),i+=1)}}function b(t){var e=!1;return function(){e||(e=!0,setTimeout(function(){e=!1,t()},Z))}}function y(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function w(t,e,i){if(Array.prototype.findIndex)return t.findIndex(function(t){return t[e]===i});var n=y(t,function(t){return t[e]===i});return t.indexOf(n)}function E(t){return st({},t,{right:t.left+t.width,bottom:t.top+t.height})}function O(t){var e=window.getComputedStyle(t),i=parseFloat(e.marginTop)+parseFloat(e.marginBottom),n=parseFloat(e.marginLeft)+parseFloat(e.marginRight);return{width:t.offsetWidth+n,height:t.offsetHeight+i}}function x(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,function(t){return e[t]})}function k(t,e,i,n){n=n.split("-")[0];var o=O(e),r={position:t,width:o.width,height:o.height},s=["right","left"].indexOf(n)!==-1,a=s?"top":"left",l=s?"left":"top",p=s?"height":"width",f=s?"width":"height";return r[a]=i[a]+i[p]/2-o[p]/2,r[l]=n===l?i[l]-o[f]:i[x(l)],r}function T(e,i,n){var o="fixed"===e.position,r=e.isParentTransformed;return f(n,t(o&&r?n:i),o,r)}function L(t){for(var e=[!1,"ms","webkit","moz","o"],i=t.charAt(0).toUpperCase()+t.slice(1),n=0;n<e.length-1;n++){var o=e[n],r=o?""+o+i:t;if(void 0!==window.document.body.style[r])return r}return null}function A(t){var e={};return t&&"[object Function]"===e.toString.call(t)}function C(t,e){return t.some(function(t){var i=t.name;return t.enabled&&i===e})}function S(t,e,i){var n=y(t,function(t){return t.name===e});return!!n&&t.some(function(t){return t.name===i&&t.enabled&&t.order<n.order})}function M(t){return""!==t&&!isNaN(parseFloat(t))&&isFinite(t)}function D(t){return"BODY"!==t.nodeName&&("none"!==e(t,"transform")||(i(t)?D(i(t)):t))}function N(t,e){return window.removeEventListener("resize",e.updateBound),e.scrollParents.forEach(function(t){t.removeEventListener("scroll",e.updateBound)}),e.updateBound=null,e.scrollParents=[],e.scrollElement=null,e.eventsEnabled=!1,e}function P(t,e,i){return(void 0===i?t:t.slice(0,w(t,"name",i))).forEach(function(t){t.enabled&&A(t.function)&&(e=t.function(e,t))}),e}function _(t,e){Object.keys(e).forEach(function(i){e[i]!==!1?t.setAttribute(i,e[i]):t.removeAttribute(i)})}function W(t,e){Object.keys(e).forEach(function(i){var n="";["width","height","top","right","bottom","left"].indexOf(i)!==-1&&M(e[i])&&(n="px"),t.style[i]=e[i]+n})}function I(t,e,i,o){var r="BODY"===t.nodeName,s=r?window:t;s.addEventListener(e,i,{passive:!0}),r||I(n(s.parentNode),e,i,o),o.push(s)}function B(t,e,i,o){i.updateBound=o,window.addEventListener("resize",i.updateBound,{passive:!0});var r=n(t);return I(r,"scroll",i.updateBound,i.scrollParents),i.scrollElement=r,i.eventsEnabled=!0,i}function H(t,e){var i={position:t.offsets.popper.position},n={"x-placement":t.placement},o=Math.round(t.offsets.popper.left),r=Math.round(t.offsets.popper.top),s=L("transform");return e.gpuAcceleration&&s?(i[s]="translate3d("+o+"px, "+r+"px, 0)",i.top=0,i.left=0,i.willChange="transform"):(i.left=o,i.top=r,i.willChange="top, left"),W(t.instance.popper,st({},i,t.styles)),_(t.instance.popper,st({},n,t.attributes)),t.offsets.arrow&&W(t.arrowElement,t.offsets.arrow),t}function F(t,e,i,n,o){var r=T(o,e,t);return i.placement=v(i.placement,r,e),e.setAttribute("x-placement",i.placement),i}function j(t,e){if(!S(t.instance.modifiers,"arrow","keepTogether"))return console.warn("WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!"),t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var n=t.placement.split("-")[0],o=E(t.offsets.popper),r=t.offsets.reference,s=["left","right"].indexOf(n)!==-1,a=s?"height":"width",l=s?"top":"left",p=s?"left":"top",f=s?"bottom":"right",u=O(i)[a];r[f]-u<o[l]&&(t.offsets.popper[l]-=o[l]-(r[f]-u)),r[l]+u>o[f]&&(t.offsets.popper[l]+=r[l]+u-o[f]);var d=r[l]+r[a]/2-u/2,c=d-E(t.offsets.popper)[l];return c=Math.max(Math.min(o[a]-u,c),0),t.arrowElement=i,t.offsets.arrow={},t.offsets.arrow[l]=c,t.offsets.arrow[p]="",t}function R(t){return"end"===t?"start":"start"===t?"end":t}function Y(t,e){if(C(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var i=m(t.instance.popper,e.padding,e.boundariesElement),n=t.placement.split("-")[0],o=x(n),r=t.placement.split("-")[1]||"",s=[];return s="flip"===e.behavior?[n,o]:e.behavior,s.forEach(function(a,l){if(n!==a||s.length===l+1)return t;n=t.placement.split("-")[0],o=x(n);var p=E(t.offsets.popper),f=t.offsets.reference,u=Math.floor,d="left"===n&&u(p.right)>u(f.left)||"right"===n&&u(p.left)<u(f.right)||"top"===n&&u(p.bottom)>u(f.top)||"bottom"===n&&u(p.top)<u(f.bottom),c=u(p.left)<u(i.left),h=u(p.right)>u(i.right),m=u(p.top)<u(i.top),v=u(p.bottom)>u(i.bottom),g="left"===n&&c||"right"===n&&h||"top"===n&&m||"bottom"===n&&v,b=["top","bottom"].indexOf(n)!==-1,y=!!e.flipVariations&&(b&&"start"===r&&c||b&&"end"===r&&h||!b&&"start"===r&&m||!b&&"end"===r&&v);(d||g||y)&&(t.flipped=!0,(d||g)&&(n=s[l+1]),y&&(r=R(r)),t.placement=n+(r?"-"+r:""),t.offsets.popper=k(t.instance.state.position,t.instance.popper,t.offsets.reference,t.placement),t=P(t.instance.modifiers,t,"flip"))}),t}function q(t){var e=E(t.offsets.popper),i=t.offsets.reference,n=t.placement.split("-")[0],o=Math.floor,r=["top","bottom"].indexOf(n)!==-1,s=r?"right":"bottom",a=r?"left":"top",l=r?"width":"height";return e[s]<o(i[a])&&(t.offsets.popper[a]=o(i[a])-e[l]),e[a]>o(i[s])&&(t.offsets.popper[a]=o(i[s])),t}function U(t,e){var i=t.placement,n=t.offsets.popper,o=void 0;return M(e.offset)?o=[e.offset,0]:(o=e.offset.split(" "),o=o.map(function(e,n){var o=e.match(/(\d*\.?\d*)(.*)/),r=+o[1],s=o[2],a=i.indexOf("right")!==-1||i.indexOf("left")!==-1;1===n&&(a=!a);var l=a?"height":"width";if(0===s.indexOf("%")){var p=void 0;switch(s){case"%p":p=t.offsets.popper;break;case"%":case"$r":default:p=t.offsets.reference}return E(p)[l]/100*r}if("vh"===s||"vw"===s){return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r}return"px"===s?+r:+e})),t.placement.indexOf("left")!==-1?(n.top+=o[0],n.left-=o[1]||0):t.placement.indexOf("right")!==-1?(n.top+=o[0],n.left+=o[1]||0):t.placement.indexOf("top")!==-1?(n.left+=o[0],n.top-=o[1]||0):t.placement.indexOf("bottom")!==-1&&(n.left+=o[0],n.top+=o[1]||0),t}function z(e,i){var n=i.boundariesElement||t(e.instance.popper),o=m(e.instance.popper,i.padding,n);i.boundaries=o;var r=i.priority,s=E(e.offsets.popper),a={primary:function(t){var e=s[t];return s[t]<o[t]&&!i.escapeWithReference&&(e=Math.max(s[t],o[t])),rt({},t,e)},secondary:function(t){var e="right"===t?"left":"top",n=s[e];return s[t]>o[t]&&!i.escapeWithReference&&(n=Math.min(s[e],o[t]-("right"===t?s.width:s.height))),rt({},e,n)}};return r.forEach(function(t){var e=["left","top"].indexOf(t)!==-1?"primary":"secondary";s=st({},s,a[e](t))}),e.offsets.popper=s,e}function G(t){var e=t.placement,i=e.split("-")[0],n=e.split("-")[1];if(n){var o=t.offsets.reference,r=E(t.offsets.popper),s=["bottom","top"].indexOf(i)!==-1,a=s?"left":"top",l=s?"width":"height",p={start:rt({},a,o[a]),end:rt({},a,o[a]+o[l]-r[l])};t.offsets.popper=st({},r,p[n])}return t}function X(t){if(!S(t.instance.modifiers,"hide","preventOverflow"))return console.warn("WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!"),t;var e=t.offsets.reference,i=y(t.instance.modifiers,function(t){return"preventOverflow"===t.name}).boundaries;if(e.bottom<i.top||e.left>i.right||e.top>i.bottom||e.right<i.left){if(t.hide===!0)return t;t.hide=!0,t.attributes["x-out-of-boundaries"]=""}else{if(t.hide===!1)return t;t.hide=!1,t.attributes["x-out-of-boundaries"]=!1}return t}function V(t){var e=t.placement,i=e.split("-")[0],n=E(t.offsets.popper),o=E(t.offsets.reference),r=["left","right"].indexOf(i)!==-1,s=["top","left"].indexOf(i)===-1;return n[r?"left":"top"]=o[e]-(s?n[r?"width":"height"]:0),t.placement=x(e),t.offsets.popper=E(n),t}for(var $=["native code","[object MutationObserverConstructor]"],J=function(t){return $.some(function(e){return(t||"").toString().indexOf(e)>-1})},K="undefined"!=typeof window,Q=["Edge","Trident","Firefox"],Z=0,tt=0;tt<Q.length;tt+=1)if(K&&navigator.userAgent.indexOf(Q[tt])>=0){Z=1;break}var et=K&&J(window.MutationObserver),it=et?g:b,nt=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},ot=function(){function t(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,i,n){return i&&t(e.prototype,i),n&&t(e,n),e}}(),rt=function(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t},st=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},at={computeAutoPlacement:v,debounce:it,findIndex:w,getBordersSize:s,getBoundaries:m,getBoundingClientRect:a,getClientRect:E,getOffsetParent:t,getOffsetRect:d,getOffsetRectRelativeToCustomParent:f,getOuterSizes:O,getParentNode:i,getPopperOffsets:k,getPosition:r,getReferenceOffsets:T,getScroll:l,getScrollParent:n,getStyleComputedProperty:e,getSupportedPropertyName:L,getTotalScroll:h,getWindowSizes:u,includeScroll:p,isFixed:o,isFunction:A,isModifierEnabled:C,isModifierRequired:S,isNative:J,isNumeric:M,isTransformed:D,removeEventListeners:N,runModifiers:P,setAttributes:_,setStyles:W,setupEventListeners:B},lt={shift:{order:100,enabled:!0,function:G},offset:{order:200,enabled:!0,function:U,offset:0},preventOverflow:{order:300,enabled:!0,function:z,priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,function:q},arrow:{order:500,enabled:!0,function:j,element:"[x-arrow]"},flip:{order:600,enabled:!0,function:Y,behavior:"flip",padding:5,boundariesElement:"viewport"},inner:{order:700,enabled:!1,function:V},hide:{order:800,enabled:!0,function:X},applyStyle:{order:900,enabled:!0,gpuAcceleration:!0,function:H,onLoad:F}},pt={placement:"bottom",eventsEnabled:!0,onCreate:function(){},onUpdate:function(){},modifiers:lt},ft=function(){function t(e,i){var n=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};nt(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(n.update)},this.update=it(this.update.bind(this)),this.options=st({},t.Defaults,o),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e.jquery?e[0]:e,this.popper=i.jquery?i[0]:i,this.modifiers=Object.keys(t.Defaults.modifiers).map(function(e){return st({name:e},t.Defaults.modifiers[e])}),this.modifiers=this.modifiers.map(function(t){var e=o.modifiers&&o.modifiers[t.name]||{};return st({},t,e)}),o.modifiers&&(this.options.modifiers=st({},t.Defaults.modifiers,o.modifiers),Object.keys(o.modifiers).forEach(function(e){if(void 0===t.Defaults.modifiers[e]){var i=o.modifiers[e];i.name=e,n.modifiers.push(i)}})),this.state.position=r(this.reference),this.modifiers=this.modifiers.sort(function(t,e){return t.order-e.order}),this.modifiers.forEach(function(t){t.enabled&&A(t.onLoad)&&t.onLoad(n.reference,n.popper,n.options,t,n.state)}),this.state.isParentTransformed=D(this.popper.parentNode),this.update();var s=this.options.eventsEnabled;s&&this.enableEventListeners(),this.state.eventsEnabled=s}return ot(t,[{key:"update",value:function(){if(!this.state.isDestroyed){var t={instance:this,styles:{},attributes:{},flipped:!1,offsets:{}};this.state.position=r(this.reference),W(this.popper,{position:this.state.position}),t.offsets.reference=T(this.state,this.popper,this.reference),t.placement=v(this.options.placement,t.offsets.reference,this.popper),t.originalPlacement=this.options.placement,t.offsets.popper=k(this.state,this.popper,t.offsets.reference,t.placement),t=P(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}},{key:"destroy",value:function(){return this.state.isDestroyed=!0,C(this.modifiers,"applyStyle")&&(this.popper.removeAttribute("x-placement"),this.popper.style.left="",this.popper.style.position="",this.popper.style.top="",this.popper.style[L("transform")]=""),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}},{key:"enableEventListeners",value:function(){this.state.eventsEnabled||(this.state=B(this.reference,this.options,this.state,this.scheduleUpdate))}},{key:"disableEventListeners",value:function(){this.state.eventsEnabled&&(window.cancelAnimationFrame(this.scheduleUpdate),this.state=N(this.reference,this.state))}}]),t}();return ft.Utils=at,ft.placements=["auto","auto-start","auto-end","top","top-start","top-end","right","right-start","right-end","bottom","bottom-start","bottom-end","left","left-start","left-end"],ft.Defaults=pt,ft})},function(t,e,i){t.exports=i(0)}]);
10
+
11
+ /**
12
+ * Simplest Tags Input Beautifier
13
+ * Copyright (c) Taufik Nurrohman
14
+ * https://github.com/tovic
15
+ * @license MIT
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");
permalink-manager.php CHANGED
@@ -2,9 +2,9 @@
2
 
3
  /**
4
  * Plugin Name: Permalink Manager
5
- * Plugin URI: https://permalinkmanager.pro
6
- * Description: Most advanced Permalink utility for Wordpress. It allows to bulk edit the permalinks & permastructures and regenerate/reset all the URIs in your Wordpress instance.
7
- * Version: 1.0.4
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
@@ -12,19 +12,21 @@
12
  * Text Domain: permalink-manager
13
  * Domain Path: /languages
14
  */
15
- // If this file is called directly, abort.
16
- if ( ! defined( 'WPINC' ) ) {
 
17
  die;
18
  }
19
 
20
  // Define the directories used to load plugin files.
21
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
22
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
23
- define( 'PERMALINK_MANAGER_VERSION', '1.0.4' );
24
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
25
  define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
26
  define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
27
- define( 'PERMALINK_MANAGER_WEBSITE', 'http://permalinkmanager.pro' );
 
28
 
29
  class Permalink_Manager_Class {
30
 
@@ -55,14 +57,16 @@ class Permalink_Manager_Class {
55
  'uri-functions-tax' => 'Permalink_Manager_URI_Functions_Tax',
56
  'admin-functions' => 'Permalink_Manager_Admin_Functions',
57
  'actions' => 'Permalink_Manager_Actions',
58
- 'pro-hooks' => 'Permalink_Manager_Pro_Hooks'
 
59
  ),
60
  'views' => array(
61
  'uri-editor' => 'Permalink_Manager_Uri_Editor',
62
  'tools' => 'Permalink_Manager_Tools',
63
  'permastructs' => 'Permalink_Manager_Permastructs',
64
  'settings' => 'Permalink_Manager_Settings',
65
- 'advanced' => 'Permalink_Manager_Advanced',
 
66
  'uri-editor-tax' => false,
67
  'uri-editor-post' => false
68
  )
@@ -98,6 +102,13 @@ class Permalink_Manager_Class {
98
 
99
  // Legacy support
100
  add_action( 'init', array($this, 'legacy_support'), 2 );
 
 
 
 
 
 
 
101
  }
102
 
103
  /**
@@ -119,17 +130,57 @@ class Permalink_Manager_Class {
119
  $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
120
 
121
  // 2. Globals used to display additional content (eg. alerts)
122
- global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
123
 
 
124
  $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', '');
125
  $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', '');
126
  }
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  /**
129
  * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin
130
  */
131
  function detect_post($query) {
132
- global $wpdb, $permalink_manager_uris, $sitepress_settings;
133
 
134
  // Check if any custom URI is used
135
  if(!(is_array($permalink_manager_uris))) return $query;
@@ -143,12 +194,11 @@ class Permalink_Manager_Class {
143
  $protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === true ? 'https://' : 'http://';
144
  $request_url = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
145
  $home_url = trim(rtrim(get_option('home'), '/'));
146
- // Adjust prefix (it should be the same in both request & home_url)
147
- $home_url = ($protocol == 'https://') ? str_replace("http://", "https://", $home_url) : str_replace("https://", "http://", $home_url);
148
 
149
  if (filter_var($request_url, FILTER_VALIDATE_URL)) {
150
  /**
151
- * 2. Process URL
152
  */
153
  // Remove .html suffix and domain name from URL and query (URLs ended with .html will work as aliases)
154
  $request_url = trim(str_replace($home_url, "", $request_url), "/");
@@ -156,20 +206,24 @@ class Permalink_Manager_Class {
156
  // Remove querystrings from URI
157
  $request_url = strtok($request_url, '?');
158
 
159
- // Split the current URL into subparts (check if WPML is active)
160
- if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) {
161
- preg_match("/^(?:(\w{2})\/)?(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $url_parts);
162
- $lang = (!empty($url_parts[1])) ? $url_parts[1] : "";
163
- $uri = (!empty($url_parts[2])) ? $url_parts[2] : "";
164
- $endpoint = (!empty($url_parts[3])) ? $url_parts[3] : "";
165
- $endpoint_value = (!empty($url_parts[4])) ? $url_parts[4] : "";
166
- } else {
167
- preg_match("/^(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $url_parts);
168
- $lang = false;
169
- $uri = (!empty($url_parts[1])) ? $url_parts[1] : "";
170
- $endpoint = (!empty($url_parts[2])) ? $url_parts[2] : "";
171
- $endpoint_value = (!empty($url_parts[3])) ? $url_parts[3] : "";
172
- }
 
 
 
 
173
 
174
  // Trim slashes
175
  $uri = trim($uri, "/");
@@ -178,7 +232,7 @@ class Permalink_Manager_Class {
178
  if(empty($uri)) return $query;
179
 
180
  /**
181
- * 2A. Check if found URI matches any element from custom uris array
182
  */
183
  $item_id = array_search($uri, $permalink_manager_uris);
184
 
@@ -186,7 +240,7 @@ class Permalink_Manager_Class {
186
  $item_id = (empty($item_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $item_id;
187
 
188
  // Check again in case someone used post/tax IDs instead of slugs
189
- $deep_detect_enabled = apply_filters('permalink_manager_deep_uri_detect', false);
190
  if($deep_detect_enabled && (empty($item_id)) && isset($old_query['page'])) {
191
  $item_id = array_search("{$uri}/{$endpoint_value}", $permalink_manager_uris);
192
  $endpoint_value = $endpoint = "";
@@ -196,12 +250,15 @@ class Permalink_Manager_Class {
196
  $query = ($item_id) ? array() : $query;
197
 
198
  /**
199
- * 2B. Custom URI assigned to taxonomy
200
  */
201
  if(strpos($item_id, 'tax-') !== false) {
202
  // Remove the "tax-" prefix
203
  $item_id = preg_replace("/[^0-9]/", "", $item_id);
204
 
 
 
 
205
  // Get the variables to filter wp_query and double-check if tax exists
206
  $term = get_term($item_id);
207
  if(empty($term->taxonomy)) { return $query; }
@@ -225,22 +282,15 @@ class Permalink_Manager_Class {
225
  $query[$query_parameter] = $final_uri;
226
  }
227
  /**
228
- * 2C. Custom URI assigned to post/page/cpt item
229
  */
230
  else if(isset($item_id) && is_numeric($item_id)) {
231
  // Fix for revisions
232
  $is_revision = wp_is_post_revision($item_id);
233
  $item_id = ($is_revision) ? $is_revision : $item_id;
234
 
235
- // Fix for WPML languages mismatch
236
- $post_lang_details = apply_filters('wpml_post_language_details', NULL, $item_id);
237
- if(is_array($post_lang_details)) {
238
- $language_code = (!empty($post_lang_details['language_code'])) ? $post_lang_details['language_code'] : '';
239
- if($lang && ($lang != $language_code)) {
240
- $wpml_item_id = apply_filters('wpml_object_id', $item_id);
241
- $item_id = (is_numeric($wpml_item_id)) ? $wpml_item_id : $item_id;
242
- }
243
- }
244
 
245
  $post_to_load = get_post($item_id);
246
  $final_uri = $post_to_load->post_name;
@@ -313,7 +363,7 @@ class Permalink_Manager_Class {
313
 
314
  // Ignore default URIs (or do nothing if redirects are disabled)
315
  if(!empty($correct_permalink) && !empty($redirect_mode)) {
316
- wp_redirect($correct_permalink, $redirect_mode);
317
  exit();
318
  }
319
  }
@@ -341,6 +391,27 @@ class Permalink_Manager_Class {
341
  }
342
  }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  }
345
 
346
  /**
@@ -349,5 +420,4 @@ class Permalink_Manager_Class {
349
  function run_permalink_manager() {
350
  $Permalink_Manager_Class = new Permalink_Manager_Class();
351
  }
352
-
353
  run_permalink_manager();
2
 
3
  /**
4
  * Plugin Name: Permalink Manager
5
+ * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6
+ * Description: Most advanced Permalink utility for Wordpress. It allows to bulk edit the permalinks & permastructures and regenerate/reset all the URIs in your Wordpress instance.
7
+ * Version: 1.1.0
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
12
  * Text Domain: permalink-manager
13
  * Domain Path: /languages
14
  */
15
+
16
+ // If this file is called directly or plugin is already defined, abort.
17
+ if (!defined('WPINC')) {
18
  die;
19
  }
20
 
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24
+ define( 'PERMALINK_MANAGER_VERSION', '1.1.0' );
25
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
26
  define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
27
  define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
28
+ define( 'PERMALINK_MANAGER_WEBSITE', 'http://permalinkmanager.pro?utm_source=plugin' );
29
+ define( 'PERMALINK_MANAGER_DONATE', 'https://www.paypal.me/Bismit' );
30
 
31
  class Permalink_Manager_Class {
32
 
57
  'uri-functions-tax' => 'Permalink_Manager_URI_Functions_Tax',
58
  'admin-functions' => 'Permalink_Manager_Admin_Functions',
59
  'actions' => 'Permalink_Manager_Actions',
60
+ 'third-parties' => 'Permalink_Manager_Third_Parties',
61
+ 'pro-functions' => 'Permalink_Manager_Pro_Functions'
62
  ),
63
  'views' => array(
64
  'uri-editor' => 'Permalink_Manager_Uri_Editor',
65
  'tools' => 'Permalink_Manager_Tools',
66
  'permastructs' => 'Permalink_Manager_Permastructs',
67
  'settings' => 'Permalink_Manager_Settings',
68
+ 'debug' => 'Permalink_Manager_Debug',
69
+ 'pro-addons' => 'Permalink_Manager_Pro_Addons',
70
  'uri-editor-tax' => false,
71
  'uri-editor-post' => false
72
  )
102
 
103
  // Legacy support
104
  add_action( 'init', array($this, 'legacy_support'), 2 );
105
+
106
+ // Check for updates
107
+ // add_action( 'init', array($this, 'check_for_updates'), 999 );
108
+
109
+ // Default settings & alerts
110
+ add_filter( 'permalink-manager-options', array($this, 'default_settings'), 1 );
111
+ add_filter( 'permalink-manager-alerts', array($this, 'default_alerts'), 1 );
112
  }
113
 
114
  /**
130
  $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
131
 
132
  // 2. Globals used to display additional content (eg. alerts)
133
+ global $permalink_manager_alerts, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
134
 
135
+ $this->permalink_manager_alerts = $permalink_manager_alerts = apply_filters('permalink-manager-alerts', get_option('permalink-manager-alerts', array()));
136
  $this->permalink_manager_before_sections_html = $permalink_manager_before_sections_html = apply_filters('permalink-manager-before-sections', '');
137
  $this->permalink_manager_after_sections_html = $permalink_manager_after_sections_html = apply_filters('permalink-manager-after-sections', '');
138
  }
139
 
140
+ /**
141
+ * Set the initial/default settings (including "Screen Options")
142
+ */
143
+ public function default_settings($settings) {
144
+ $all_taxonomies = Permalink_Manager_Helper_Functions::get_taxonomies_array();
145
+ $all_post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
146
+
147
+ $default_settings = apply_filters('permalink-manager-default-options', array(
148
+ 'screen-options' => array(
149
+ 'per_page' => 20,
150
+ 'post_statuses' => array('publish')
151
+ ),
152
+ 'general' => array(
153
+ 'force_custom_slugs' => 0,
154
+ 'auto_update_uris' => 0,
155
+ ),
156
+ 'miscellaneous' => array(
157
+ 'yoast_primary_term' => 1,
158
+ 'redirect' => "302",
159
+ 'canonical_redirect' => 1,
160
+ )
161
+ ));
162
+
163
+ // Apply the default settings (if empty values) in all settings sections
164
+ return $settings + $default_settings;
165
+ }
166
+
167
+ /**
168
+ * Set the initial/default admin notices
169
+ */
170
+ public function default_alerts($alerts) {
171
+ $default_alerts = apply_filters('permalink-manager-default-alerts', array(
172
+ // 'pro' => array('txt' => sprintf(__("Need to change the permalinks for categories, tags, custom taxonomies or WooCommerce?<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and enjoy the additional features!</strong>", "permalink-manager"), PERMALINK_MANAGER_WEBSITE), 'type' => 'notice-info', 'show' => 1)
173
+ ));
174
+
175
+ // Apply the default settings (if empty values) in all settings sections
176
+ return $alerts + $default_alerts;
177
+ }
178
+
179
  /**
180
  * Used to optimize SQL queries amount instead of rewrite rules - the essential part of this plugin
181
  */
182
  function detect_post($query) {
183
+ global $wpdb, $permalink_manager_uris, $wp_filter;
184
 
185
  // Check if any custom URI is used
186
  if(!(is_array($permalink_manager_uris))) return $query;
194
  $protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === true ? 'https://' : 'http://';
195
  $request_url = "{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
196
  $home_url = trim(rtrim(get_option('home'), '/'));
197
+ $home_url = ($protocol == 'https://') ? str_replace("http://", "https://", $home_url) : str_replace("https://", "http://", $home_url); // Adjust prefix (it should be the same in both request & home_url)
 
198
 
199
  if (filter_var($request_url, FILTER_VALIDATE_URL)) {
200
  /**
201
+ * 1. Process URL & find the URI
202
  */
203
  // Remove .html suffix and domain name from URL and query (URLs ended with .html will work as aliases)
204
  $request_url = trim(str_replace($home_url, "", $request_url), "/");
206
  // Remove querystrings from URI
207
  $request_url = strtok($request_url, '?');
208
 
209
+ // Use default REGEX to detect post
210
+ preg_match("/^(.+?)\/?(page|feed|embed|attachment|track)?(?:\/([\d+]))?\/?$/i", $request_url, $regex_parts);
211
+ $uri_parts['lang'] = false;
212
+ $uri_parts['uri'] = (!empty($regex_parts[1])) ? $regex_parts[1] : "";
213
+ $uri_parts['endpoint'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
214
+ $uri_parts['endpoint_value'] = (!empty($regex_parts[3])) ? $regex_parts[3] : "";
215
+
216
+ // Allow to filter the results by third-parties
217
+ $uri_parts = apply_filters('permalink-manager-detect-uri', $uri_parts, $request_url);
218
+
219
+ // Stop the function if $uri_parts is empty
220
+ if(empty($uri_parts)) return $query;
221
+
222
+ // Get the URI parts from REGEX parts
223
+ $lang = $uri_parts['lang'];
224
+ $uri = $uri_parts['uri'];
225
+ $endpoint = $uri_parts['endpoint'];
226
+ $endpoint_value = $uri_parts['endpoint_value'];
227
 
228
  // Trim slashes
229
  $uri = trim($uri, "/");
232
  if(empty($uri)) return $query;
233
 
234
  /**
235
+ * 2. Check if found URI matches any element from custom uris array
236
  */
237
  $item_id = array_search($uri, $permalink_manager_uris);
238
 
240
  $item_id = (empty($item_id)) ? array_search("{$uri}.html", $permalink_manager_uris) : $item_id;
241
 
242
  // Check again in case someone used post/tax IDs instead of slugs
243
+ $deep_detect_enabled = apply_filters('permalink-manager-deep-uri-detect', false);
244
  if($deep_detect_enabled && (empty($item_id)) && isset($old_query['page'])) {
245
  $item_id = array_search("{$uri}/{$endpoint_value}", $permalink_manager_uris);
246
  $endpoint_value = $endpoint = "";
250
  $query = ($item_id) ? array() : $query;
251
 
252
  /**
253
+ * 3A. Custom URI assigned to taxonomy
254
  */
255
  if(strpos($item_id, 'tax-') !== false) {
256
  // Remove the "tax-" prefix
257
  $item_id = preg_replace("/[^0-9]/", "", $item_id);
258
 
259
+ // Filter detected post ID
260
+ $item_id = apply_filters('permalink-manager-detected-term-id', $item_id, $uri_parts);
261
+
262
  // Get the variables to filter wp_query and double-check if tax exists
263
  $term = get_term($item_id);
264
  if(empty($term->taxonomy)) { return $query; }
282
  $query[$query_parameter] = $final_uri;
283
  }
284
  /**
285
+ * 3B. Custom URI assigned to post/page/cpt item
286
  */
287
  else if(isset($item_id) && is_numeric($item_id)) {
288
  // Fix for revisions
289
  $is_revision = wp_is_post_revision($item_id);
290
  $item_id = ($is_revision) ? $is_revision : $item_id;
291
 
292
+ // Filter detected post ID
293
+ $item_id = apply_filters('permalink-manager-detected-post-id', $item_id, $uri_parts);
 
 
 
 
 
 
 
294
 
295
  $post_to_load = get_post($item_id);
296
  $final_uri = $post_to_load->post_name;
363
 
364
  // Ignore default URIs (or do nothing if redirects are disabled)
365
  if(!empty($correct_permalink) && !empty($redirect_mode)) {
366
+ wp_safe_redirect($correct_permalink, $redirect_mode);
367
  exit();
368
  }
369
  }
391
  }
392
  }
393
 
394
+ /**
395
+ * Update check
396
+ */
397
+ public function check_for_updates() {
398
+ global $permalink_manager_options;
399
+
400
+ // Load Plugin Update Checker by YahnisElsts
401
+ require_once PERMALINK_MANAGER_DIR . '/includes/ext/plugin-update-checker/plugin-update-checker.php';
402
+
403
+ // Get the licence key
404
+ $license_key = (!empty($permalink_manager_options['miscellaneous']['license_key'])) ? $permalink_manager_options['miscellaneous']['license_key'] : "";
405
+
406
+ $UpdateChecker = Puc_v4_Factory::buildUpdateChecker(
407
+ "https://updates.permalinkmanager.pro/?action=get_metadata&slug=permalink-manager-pro&license_key={$license_key}",
408
+ __FILE__,
409
+ "permalink-manager-pro"
410
+ );
411
+
412
+ $file = PERMALINK_MANAGER_BASENAME;
413
+ }
414
+
415
  }
416
 
417
  /**
420
  function run_permalink_manager() {
421
  $Permalink_Manager_Class = new Permalink_Manager_Class();
422
  }
 
423
  run_permalink_manager();