Permalink Manager Lite - Version 2.0.6.2a

Version Description

Download this release

Release Info

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

Code changes from version 2.0.5.9a to 2.0.6.2a

README.txt CHANGED
@@ -4,10 +4,10 @@ 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, custom permalinks, url, permalink, woocommerce permalinks
7
- Requires at least: 4.0
8
  Requires PHP: 5.4
9
  Tested up to: 4.9
10
- Stable tag: 2.0.5.9
11
 
12
  Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
13
 
@@ -90,16 +90,32 @@ A. Currently there is no 100% guarantee that Permalink Manager will work correct
90
  1. "Permalink editor".
91
  2. "Find and replace" section.
92
  3. "Regenerate/Reset" section.
93
- 4. "Permastructures" section.
94
- 5. A list of updated posts.
95
- 6. Editable URI box in Post/Page/CPT edit pagees.
96
- 7. Settings section.
97
 
98
 
99
  == Changelog ==
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  = 2.0.5.9 =
102
  * New permastructure tags - %post_type% & %taxonomy%
 
 
 
103
 
104
  = 2.0.5.7/2.0.5.8 =
105
  * Hotfix for MultilingualPress plugin
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
6
  Tags: urls, permalinks, custom permalinks, url, permalink, woocommerce permalinks
7
+ Requires at least: 4.4.0
8
  Requires PHP: 5.4
9
  Tested up to: 4.9
10
+ Stable tag: 2.0.6.2
11
 
12
  Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
13
 
90
  1. "Permalink editor".
91
  2. "Find and replace" section.
92
  3. "Regenerate/Reset" section.
93
+ 4. "Permastructures" section.
94
+ 5. A list of updated posts.
95
+ 6. Editable URI box in Post/Page/CPT edit pagees.
96
+ 7. Settings section.
97
 
98
 
99
  == Changelog ==
100
 
101
+ = 2.0.6.1/2.0.6.2 =
102
+ * Hotfix for endpoints in REGEX
103
+ * Minor bug fixed - native slugs are now correctly regenerated
104
+ * Hotfix for URI sanitization functions
105
+ * Hotfix for AMP plugin
106
+ * Full support for WPML multi-domain language setup
107
+
108
+ = 2.0.6.0 =
109
+ * Minor bugs fixed
110
+ * New permastrutcure tag - %native_slug%
111
+ * "Force custom slugs" feature enhanced with new options
112
+ * Possibility to redirect the posts & terms to external URL (Permalink Manager Pro)
113
+
114
  = 2.0.5.9 =
115
  * New permastructure tags - %post_type% & %taxonomy%
116
+ * Support for "Taxonomy" custom field in ACF (Advanced Custom Fields)
117
+ * Minor fix for endpoints
118
+ * New hook - "permalink_manager-filter-permalink-base" used instead of "permalink-manager-post-permalink-prefix" & "permalink-manager-term-permalink-prefix"
119
 
120
  = 2.0.5.7/2.0.5.8 =
121
  * Hotfix for MultilingualPress plugin
includes/core/permalink-manager-admin-functions.php CHANGED
@@ -265,7 +265,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
265
  return "<div class=\"clearfix\"></div>";
266
 
267
  case 'permastruct' :
268
- $siteurl = get_option('home');
269
  $fields .= "<div class=\"permastruct-container\"><span><code>{$siteurl}/</code></span><span><input type='text' {$input_atts} value='{$value}' name='{$input_name}'/></span></div>";
270
  break;
271
 
@@ -575,7 +575,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
575
  /**
576
  * Display "Permalink Manager" box
577
  */
578
- public static function display_uri_box($element, $default_uri, $uri, $native_uri, $home_with_prefix) {
579
  global $permalink_manager_options;
580
 
581
  if(!empty($element->ID)) {
@@ -611,7 +611,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
611
  $html .= "<div class=\"inside\">";
612
 
613
  // 4. Custom URI
614
- if(get_option('page_on_front') == $id) {
615
  $custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("type" => "hidden", "extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => urldecode($uri)));
616
  $custom_uri_field .= __("The custom URI cannot be edited on frontpage.", "permalink-manager");
617
  } else {
@@ -644,10 +644,13 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
644
 
645
  // 7. Native URI info
646
  if(!empty($permalink_manager_options['general']['redirect']) && ((!empty($element->post_status) && in_array($element->post_status, array('auto-draft', 'trash', 'draft'))) == false)) {
 
 
 
647
  $html .= sprintf(
648
  "<div class=\"default-permalink-row columns-container\"><span><strong>%s</strong> <a href=\"%s\">%s</a></span></div>",
649
  __("Automatic redirect for native URI enabled:", "permalink-manager"),
650
- "{$home_with_prefix}{$native_uri}",
651
  urldecode($native_uri)
652
  );
653
  }
@@ -674,8 +677,9 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
674
 
675
  // Heading
676
  $html = sprintf(
677
- "<div class=\"permalink-manager redirects-row redirects-panel columns-container\"><div class=\"heading\"><span class=\"dashicons dashicons-redo\"></span> <a href=\"#\" id=\"toggle-redirect-panel\">%s</a></span></div>",
678
- __("Add Extra Redirects", "permalink-manager")
 
679
  );
680
 
681
  $html .= "<div id=\"redirect-panel-inside\">";
265
  return "<div class=\"clearfix\"></div>";
266
 
267
  case 'permastruct' :
268
+ $siteurl = Permalink_Manager_Helper_Functions::get_permalink_base();
269
  $fields .= "<div class=\"permastruct-container\"><span><code>{$siteurl}/</code></span><span><input type='text' {$input_atts} value='{$value}' name='{$input_name}'/></span></div>";
270
  break;
271
 
575
  /**
576
  * Display "Permalink Manager" box
577
  */
578
+ public static function display_uri_box($element, $default_uri, $uri, $native_uri) {
579
  global $permalink_manager_options;
580
 
581
  if(!empty($element->ID)) {
611
  $html .= "<div class=\"inside\">";
612
 
613
  // 4. Custom URI
614
+ if(!empty($element->ID) && get_option('page_on_front') == $id) {
615
  $custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("type" => "hidden", "extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => urldecode($uri)));
616
  $custom_uri_field .= __("The custom URI cannot be edited on frontpage.", "permalink-manager");
617
  } else {
644
 
645
  // 7. Native URI info
646
  if(!empty($permalink_manager_options['general']['redirect']) && ((!empty($element->post_status) && in_array($element->post_status, array('auto-draft', 'trash', 'draft'))) == false)) {
647
+ $native_permalink = trim(Permalink_Manager_Helper_Functions::get_permalink_base($element), "/") . "/";
648
+ $native_permalink .= $native_uri;
649
+
650
  $html .= sprintf(
651
  "<div class=\"default-permalink-row columns-container\"><span><strong>%s</strong> <a href=\"%s\">%s</a></span></div>",
652
  __("Automatic redirect for native URI enabled:", "permalink-manager"),
653
+ $native_permalink,
654
  urldecode($native_uri)
655
  );
656
  }
677
 
678
  // Heading
679
  $html = sprintf(
680
+ "<div class=\"permalink-manager redirects-row redirects-panel columns-container\"><div class=\"heading\"><span class=\"dashicons dashicons-edit\"></span> <a href=\"#\" id=\"toggle-redirect-panel\">%s <small>%s</small></a></span></div>",
681
+ __("Manage redirects", "permalink-manager"),
682
+ __("[click to open]", "permalink-manager")
683
  );
684
 
685
  $html .= "<div id=\"redirect-panel-inside\">";
includes/core/permalink-manager-core-functions.php CHANGED
@@ -69,7 +69,9 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
69
 
70
  // Get all the endpoints & pattern
71
  $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
72
- $pattern = "/^(.+?)(?|\/({$endpoints})\/?([^\/]*)|()\/([\d+]))?\/?$/i";
 
 
73
 
74
  // Use default REGEX to detect post
75
  preg_match($pattern, $request_url, $regex_parts);
@@ -112,8 +114,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
112
  $element_id = (empty($element_id)) ? array_search("{$uri}.html", $all_uris) : $element_id;
113
 
114
  // Check again in case someone used post/tax IDs instead of slugs
115
- if($deep_detect_enabled && isset($old_query['page'])) {
116
-
117
  $new_item_id = array_search("{$uri}/{$endpoint_value}", $all_uris);
118
  if($new_item_id) {
119
  $element_id = $new_item_id;
@@ -242,7 +243,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
242
  /**
243
  * 5A. Endpoints
244
  */
245
- if($element_id && (!empty($endpoint)) || !empty($endpoint_value)) {
246
  $endpoint = ($endpoint) ? str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint) : "page";
247
 
248
  if($endpoint == 'feed') {
@@ -262,7 +263,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
262
  /**
263
  * 5B. Endpoints - check if any endpoint is set with $_GET parameter
264
  */
265
- if($deep_detect_enabled && !empty($_GET)) {
266
  $get_endpoints = array_intersect($wp->public_query_vars, array_keys($_GET));
267
 
268
  if(!empty($get_endpoints)) {
@@ -386,7 +387,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
386
  * Redirects
387
  */
388
  function new_uri_redirect_and_404() {
389
- global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_options, $wp, $pm_query, $pm_uri_parts;
390
 
391
  // Do not redirect on author pages & front page
392
  if(is_author() || is_front_page() || is_home()) { return false; }
@@ -411,7 +412,19 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
411
  $home_url = rtrim(get_option('home'), "/");
412
 
413
  /**
414
- * 1A. Custom redirects
 
 
 
 
 
 
 
 
 
 
 
 
415
  */
416
  if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request) && !empty($pm_query['uri'])) {
417
  $uri = $pm_query['uri'];
@@ -437,7 +450,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
437
  if(!empty($_SERVER['REQUEST_URI']) && (strpos($_SERVER['REQUEST_URI'], '/wp-content') !== false)) { return false; }
438
 
439
  /**
440
- * 1B. Enhance native redirect
441
  */
442
  if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) {
443
  // Affect only posts with custom URI and old URIs
69
 
70
  // Get all the endpoints & pattern
71
  $endpoints = Permalink_Manager_Helper_Functions::get_endpoints();
72
+ //$pattern = "/^(.+?)(?|\/({$endpoints})\/?([^\/]*)|()\/([\d+]))?\/?$/i";
73
+ //$pattern = "/^(.+?)(?|\/({$endpoints})[\/$]([^\/]*)|()\/([\d+]))?\/?$/i";
74
+ $pattern = "/^(.+?)(?|\/({$endpoints})(?|\/(.*)|$)|\/()([\d]+)\/?)?$/i";
75
 
76
  // Use default REGEX to detect post
77
  preg_match($pattern, $request_url, $regex_parts);
114
  $element_id = (empty($element_id)) ? array_search("{$uri}.html", $all_uris) : $element_id;
115
 
116
  // Check again in case someone used post/tax IDs instead of slugs
117
+ if($deep_detect_enabled && (isset($old_query['page']) || isset($old_query['paged']))) {
 
118
  $new_item_id = array_search("{$uri}/{$endpoint_value}", $all_uris);
119
  if($new_item_id) {
120
  $element_id = $new_item_id;
243
  /**
244
  * 5A. Endpoints
245
  */
246
+ if(!empty($element_id) && ((!empty($endpoint)) || !empty($endpoint_value))) {
247
  $endpoint = ($endpoint) ? str_replace(array('page', 'trackback'), array('paged', 'tb'), $endpoint) : "page";
248
 
249
  if($endpoint == 'feed') {
263
  /**
264
  * 5B. Endpoints - check if any endpoint is set with $_GET parameter
265
  */
266
+ if(!empty($element_id) && $deep_detect_enabled && !empty($_GET)) {
267
  $get_endpoints = array_intersect($wp->public_query_vars, array_keys($_GET));
268
 
269
  if(!empty($get_endpoints)) {
387
  * Redirects
388
  */
389
  function new_uri_redirect_and_404() {
390
+ global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_external_redirects, $permalink_manager_options, $wp, $pm_query, $pm_uri_parts;
391
 
392
  // Do not redirect on author pages & front page
393
  if(is_author() || is_front_page() || is_home()) { return false; }
412
  $home_url = rtrim(get_option('home'), "/");
413
 
414
  /**
415
+ * 1A. External redirect
416
+ */
417
+ if(!empty($pm_query['id']) && !empty($permalink_manager_external_redirects[$pm_query['id']])) {
418
+ $external_url = $permalink_manager_external_redirects[$pm_query['id']];
419
+
420
+ if(filter_var($external_url, FILTER_VALIDATE_URL)) {
421
+ wp_redirect($external_url, 301);
422
+ exit();
423
+ }
424
+ }
425
+
426
+ /**
427
+ * 1B. Custom redirects
428
  */
429
  if(empty($wp_query->query_vars['do_not_redirect']) && !empty($permalink_manager_redirects) && is_array($permalink_manager_redirects) && !empty($wp->request) && !empty($pm_query['uri'])) {
430
  $uri = $pm_query['uri'];
450
  if(!empty($_SERVER['REQUEST_URI']) && (strpos($_SERVER['REQUEST_URI'], '/wp-content') !== false)) { return false; }
451
 
452
  /**
453
+ * 1C. Enhance native redirect
454
  */
455
  if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) {
456
  // Affect only posts with custom URI and old URIs
includes/core/permalink-manager-helper-functions.php CHANGED
@@ -8,8 +8,8 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
8
  public function __construct() { }
9
 
10
  /**
11
- * Support for multidimensional arrays - array_map()
12
- */
13
  static function multidimensional_array_map($function, $input) {
14
  $output = array();
15
 
@@ -25,8 +25,8 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
25
  }
26
 
27
  /**
28
- * Get primary term (by Yoast SEO)
29
- */
30
  static function get_primary_term($post_id, $taxonomy, $slug_only = true) {
31
  global $permalink_manager_options;
32
 
@@ -43,6 +43,89 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
43
  return '';
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  static function content_types_disabled_by_default($is_taxonomy = false) {
47
  if($is_taxonomy) {
48
  return array('product_shipping_class');
@@ -284,19 +367,10 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
284
  }
285
 
286
  /**
287
- * Get default language (WPML & Polylang)
288
  */
289
- static function get_language() {
290
- global $sitepress;
291
- $def_lang = '';
292
-
293
- if(function_exists('pll_default_language')) {
294
- $def_lang = pll_default_language('slug');
295
- } else if(is_object($sitepress)) {
296
- $def_lang = $sitepress->get_default_language();
297
- }
298
-
299
- return $def_lang;
300
  }
301
 
302
  /**
@@ -328,22 +402,33 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
328
  /**
329
  * Slugify function
330
  */
331
- public static function sanitize_title($str, $keep_percent_sign = false) {
 
 
 
 
 
 
 
 
332
  // Trim slashes & whitespaces
333
  $clean = trim($str, " /");
334
 
335
  // Remove accents
336
  $clean = remove_accents($clean);
337
 
338
- // Foree lowercase & hyphens
339
- $force_lowercase = apply_filters('permalink-manager-force-lowercase-uris', true);
340
- $force_hyphens = apply_filters('permalink-manager-force-hyphens', true);
341
-
342
  // $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $clean);
343
  $percent_sign = ($keep_percent_sign) ? "\%" : "";
344
  $clean = preg_replace("/[^\p{L}a-zA-Z0-9{$percent_sign}\/_\.|+ -]/u", '', $clean);
345
  $clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-');
346
- $clean = ($force_hyphens) ? preg_replace("/[_|+ -]+/", "-", $clean) : $clean;
 
 
 
 
 
 
 
347
 
348
  return $clean;
349
  }
@@ -355,8 +440,10 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
355
  global $permalink_manager_options;
356
 
357
  if(!empty($permalink_manager_options['general']['force_custom_slugs'])) {
 
 
358
  $old_slug = basename($slug);
359
- $new_slug = (!empty($object->name)) ? sanitize_title($object->name) : self::sanitize_title($object->post_title);
360
 
361
  $slug = ($old_slug != $new_slug) ? str_replace($old_slug, $new_slug, $slug) : $slug;
362
  }
8
  public function __construct() { }
9
 
10
  /**
11
+ * Support for multidimensional arrays - array_map()
12
+ */
13
  static function multidimensional_array_map($function, $input) {
14
  $output = array();
15
 
25
  }
26
 
27
  /**
28
+ * Get primary term (by Yoast SEO)
29
+ */
30
  static function get_primary_term($post_id, $taxonomy, $slug_only = true) {
31
  global $permalink_manager_options;
32
 
43
  return '';
44
  }
45
 
46
+ /**
47
+ * Get lowest level term/post
48
+ */
49
+ static function get_lowest_element($first_element, $elements) {
50
+ if(!empty($elements) && !empty($first_element)) {
51
+ // Get the ID of first element
52
+ if(!empty($first_element->term_id)) {
53
+ $first_element_id = $first_element->term_id;
54
+ $parent_key = 'parent';
55
+ } else if(!empty($first_element->ID)) {
56
+ $first_element_id = $first_element->ID;
57
+ $parent_key = 'post_parent';
58
+ } else if(is_numeric($first_element)) {
59
+ $first_element_id = $first_element;
60
+ $parent_key = 'post_parent';
61
+ } else {
62
+ return false;
63
+ }
64
+
65
+ $children = wp_filter_object_list($elements, array($parent_key => $first_element_id));
66
+ if(!empty($children)) {
67
+ // Get the first term
68
+ $child_term = reset($children);
69
+ $first_element = self::get_lowest_element($child_term, $elements);
70
+ }
71
+ }
72
+ return $first_element;
73
+ }
74
+
75
+ /**
76
+ * Get term full slug
77
+ */
78
+ static function get_term_full_slug($term, $terms, $mode = false, $native_uri = false) {
79
+ global $permalink_manager_uris;
80
+
81
+ // Check if term is not empty
82
+ if(empty($term->taxonomy)) { return ''; }
83
+
84
+ // Get taxonomy
85
+ $taxonomy = $term->taxonomy;
86
+
87
+ // Check if mode is set
88
+ if(empty($mode)) {
89
+ $mode = (is_taxonomy_hierarchical($taxonomy)) ? 2 : 4;
90
+ }
91
+
92
+ // A. Get permalink base from the term's custom URI
93
+ if($mode == 1) {
94
+ $term_slug = $permalink_manager_uris["tax-{$term->term_id}"];
95
+ }
96
+ // B. Hierarhcical taxonomy base
97
+ else if($mode == 2) {
98
+ $ancestors = get_ancestors($term->term_id, $taxonomy, 'taxonomy');
99
+ $hierarchical_slugs = array();
100
+
101
+ foreach((array) $ancestors as $ancestor) {
102
+ $ancestor_term = get_term($ancestor, $taxonomy);
103
+ $hierarchical_slugs[] = ($native_uri) ? $ancestor_term->slug : self::force_custom_slugs($ancestor_term->slug, $ancestor_term);
104
+ }
105
+ $hierarchical_slugs = array_reverse($hierarchical_slugs);
106
+ $term_slug = implode('/', $hierarchical_slugs);
107
+
108
+ // Append the term slug now
109
+ $last_term_slug = ($native_uri) ? $term->slug : self::force_custom_slugs($term->slug, $term);
110
+ $term_slug = "{$term_slug}/{$last_term_slug}";
111
+ }
112
+ // C. Force flat taxonomy base - get highgest level term (if %taxonomy_flat% tag is used)
113
+ else if($mode == 3) {
114
+ foreach($terms as $single_term) {
115
+ if($single_term->parent == 0) {
116
+ $term_slug = self::force_custom_slugs($single_term->slug, $single_term);
117
+ break;
118
+ }
119
+ }
120
+ }
121
+ // D. Flat/non-hierarchical taxonomy base - get primary term (if set) or first term
122
+ else if(!empty($term->slug)) {
123
+ $term_slug = ($native_uri) ? $term->slug : Permalink_Manager_Helper_Functions::force_custom_slugs($term->slug, $term);
124
+ }
125
+
126
+ return (!empty($term_slug)) ? $term_slug : "";
127
+ }
128
+
129
  static function content_types_disabled_by_default($is_taxonomy = false) {
130
  if($is_taxonomy) {
131
  return array('product_shipping_class');
367
  }
368
 
369
  /**
370
+ * Get permalink base (home URL)
371
  */
372
+ public static function get_permalink_base($element = null) {
373
+ return apply_filters('permalink_manager-filter-permalink-base', trim(get_option('home'), "/"), $element);
 
 
 
 
 
 
 
 
 
374
  }
375
 
376
  /**
402
  /**
403
  * Slugify function
404
  */
405
+ public static function sanitize_title($str, $keep_percent_sign = false, $force_lowercase = null, $sanitize_slugs = null) {
406
+ global $permalink_manager_options;
407
+
408
+ // Foree lowercase & hyphens
409
+ $force_lowercase = (!is_null($force_lowercase)) ? $force_lowercase : apply_filters('permalink-manager-force-lowercase-uris', true);
410
+ if(!is_null($sanitize_slugs)) {
411
+ $sanitize_slugs = ($permalink_manager_options['general']['force_custom_slugs'] == 2) ? false : true;
412
+ }
413
+
414
  // Trim slashes & whitespaces
415
  $clean = trim($str, " /");
416
 
417
  // Remove accents
418
  $clean = remove_accents($clean);
419
 
 
 
 
 
420
  // $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $clean);
421
  $percent_sign = ($keep_percent_sign) ? "\%" : "";
422
  $clean = preg_replace("/[^\p{L}a-zA-Z0-9{$percent_sign}\/_\.|+ -]/u", '', $clean);
423
  $clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-');
424
+
425
+ // Remove special characters
426
+ if($sanitize_slugs) {
427
+ $clean = preg_replace("/[\s_|+-]+/", "-", $clean);
428
+ $clean = preg_replace("/[\.]+/", "", $clean);
429
+ } else {
430
+ $clean = preg_replace("/[\s]+/", "-", $clean);
431
+ }
432
 
433
  return $clean;
434
  }
440
  global $permalink_manager_options;
441
 
442
  if(!empty($permalink_manager_options['general']['force_custom_slugs'])) {
443
+ $title = (!empty($object->name)) ? $object->name : $object->post_title;
444
+
445
  $old_slug = basename($slug);
446
+ $new_slug = self::sanitize_title($title, false);
447
 
448
  $slug = ($old_slug != $new_slug) ? str_replace($old_slug, $new_slug, $slug) : $slug;
449
  }
includes/core/permalink-manager-third-parties.php CHANGED
@@ -12,19 +12,23 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
12
  function init_hooks() {
13
  global $sitepress_settings, $permalink_manager_options, $polylang;
14
 
 
 
 
15
  // 1. WPML & Polylang
16
  if($sitepress_settings || !empty($polylang->links_model->options)) {
17
  // Detect Post/Term function
18
- add_filter('permalink-manager-detected-post-id', array($this, 'wpml_language_mismatch_fix'), 9, 3);
19
- add_filter('permalink-manager-detected-term-id', array($this, 'wpml_language_mismatch_fix'), 9, 3);
 
 
20
 
21
  // URI Editor
22
  add_filter('permalink-manager-uri-editor-extra-info', array($this, 'wpml_lang_column_content_uri_editor'), 9, 3);
23
 
24
- if((isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 1) || (isset($polylang->links_model->options['force_lang']) && $polylang->links_model->options['force_lang'] == 1)) {
25
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_detect_post'), 9, 3);
26
- add_filter('permalink-manager-post-permalink-prefix', array($this, 'wpml_element_lang_prefix'), 9, 3);
27
- add_filter('permalink-manager-term-permalink-prefix', array($this, 'wpml_element_lang_prefix'), 9, 3);
28
  add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 );
29
  } else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) {
30
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9);
@@ -77,9 +81,56 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
77
  }
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  /**
81
  * 1. WPML filters
82
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  function wpml_language_mismatch_fix($item_id, $uri_parts, $is_term = false) {
84
  global $wp, $language_code;
85
 
@@ -87,19 +138,22 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
87
  $element = get_term($item_id);
88
  if(!empty($element) && !is_wp_error($element)) {
89
  $element_id = $element->term_taxonomy_id;
90
- $element_type = $element->taxonomy;
91
  } else {
92
  return false;
93
  }
94
  } else {
95
- $element_type = get_post_type($item_id);
96
- $element_id = $item_id;
 
 
 
 
97
  }
98
 
99
  // Stop if no term or post is detected
100
- if(empty($element_id)) { return false; }
101
 
102
- $language_code = apply_filters('wpml_element_language_code', null, array('element_id' => $element_id, 'element_type' => $element_type));
103
 
104
  if(!empty($uri_parts['lang']) && ($uri_parts['lang'] != $language_code)) {
105
  $wpml_item_id = apply_filters('wpml_object_id', $element_id);
@@ -121,8 +175,20 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
121
  $default_language = pll_default_language();
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
124
  if(!empty($languages_list)) {
125
- preg_match("/^(?:({$languages_list})\/)?(.+?)(?|\/({$endpoints})\/?([^\/]*)|\/()([\d+]))?\/?$/i", $request_url, $regex_parts);
 
126
 
127
  $uri_parts['lang'] = (!empty($regex_parts[1])) ? $regex_parts[1] : $default_language;
128
  $uri_parts['uri'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
@@ -133,52 +199,69 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
133
  return $uri_parts;
134
  }
135
 
136
- function wpml_element_lang_prefix($prefix, $element, $edit_uri_box = false) {
137
- global $sitepress_settings, $polylang;
138
 
139
- if(isset($element->post_type)) {
140
- $post = (is_integer($element)) ? get_post($element) : $element;
141
- $element_id = $post->ID;
142
- $element_type = $post->post_type;
143
- } else {
144
- $term = (is_numeric($element)) ? get_term(intval($element)) : $element;
145
- $element_id = $term->term_taxonomy_id;
146
- $element_type = $term->taxonomy;
147
- }
148
 
149
- $language_code = apply_filters( 'wpml_element_language_code', null, array('element_id' => $element_id, 'element_type' => $element_type));
150
-
151
- if($edit_uri_box) {
152
- // Last instance - use language paramater from &_GET array
153
  $language_code = (empty($language_code) && !empty($_GET['lang'])) ? $_GET['lang'] : $language_code;
154
  }
155
 
156
- // Append slash to the end of language code if it is not empty
157
  if(!empty($language_code)) {
158
- $prefix = "{$language_code}/";
 
 
 
 
 
 
 
 
 
159
 
160
- // Hide language code if "Use directory for default language" option is enabled
161
- $default_language = Permalink_Manager_Helper_Functions::get_language();
162
- $hide_prefix_for_default_lang = ((isset($sitepress_settings['urls']['directory_for_default_language']) && $sitepress_settings['urls']['directory_for_default_language'] != 1) || !empty($polylang->links_model->options['hide_default'])) ? true : false;
163
 
164
- if($hide_prefix_for_default_lang && ($default_language == $language_code)) {
165
- $prefix = "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  }
167
  }
168
 
169
- return $prefix;
170
  }
171
 
172
  function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) {
173
- $translations = WPML_Slug_Translation::get_translations($post_type);
174
-
175
- if(empty($translations[1])) { return $post_type_slug; }
176
-
177
  $post = (is_integer($element)) ? get_post($element) : $element;
178
- $language_code = apply_filters( 'wpml_element_language_code', null, array('element_id' => $post->ID, 'element_type' => $post_type));
 
 
179
 
180
  // Translate %post_type% tag in custom permastructures
181
- return (!empty($translations[1][$language_code]['value'])) ? $translations[1][$language_code]['value'] : $post_type_slug;
182
  }
183
 
184
  function wpml_lang_column_uri_editor($columns) {
@@ -190,17 +273,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
190
  }
191
 
192
  function wpml_lang_column_content_uri_editor($output, $column, $element) {
193
- if(isset($element->post_type)) {
194
- $post = (is_integer($element)) ? get_post($element) : $element;
195
- $element_id = $post->ID;
196
- $element_type = $post->post_type;
197
- } else {
198
- $term = (is_numeric($element)) ? get_term(intval($element)) : $element;
199
- $element_id = $term->term_taxonomy_id;
200
- $element_type = $term->taxonomy;
201
- }
202
-
203
- $language_code = apply_filters( 'wpml_element_language_code', null, array('element_id' => $element_id, 'element_type' => $element_type));
204
  $output .= (!empty($language_code)) ? sprintf(" | <span><strong>%s:</strong> %s</span>", __("Language"), $language_code) : "";
205
 
206
  return $output;
@@ -232,7 +305,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
232
  $amp_query_var = AMP_QUERY_VAR;
233
 
234
  // Check if AMP should be triggered
235
- preg_match("/^(.+?)\/?({$amp_query_var})?\/?$/i", $uri_parts['uri'], $regex_parts);
236
  if(!empty($regex_parts[2])) {
237
  $uri_parts['uri'] = $regex_parts[1];
238
  $amp_enabled = true;
12
  function init_hooks() {
13
  global $sitepress_settings, $permalink_manager_options, $polylang;
14
 
15
+ // 0. Stop redirect
16
+ add_action('wp', array($this, 'stop_redirect'), 0);
17
+
18
  // 1. WPML & Polylang
19
  if($sitepress_settings || !empty($polylang->links_model->options)) {
20
  // Detect Post/Term function
21
+ if(!empty($permalink_manager_options['general']['fix_language_mismatch'])) {
22
+ add_filter('permalink-manager-detected-post-id', array($this, 'wpml_language_mismatch_fix'), 9, 3);
23
+ add_filter('permalink-manager-detected-term-id', array($this, 'wpml_language_mismatch_fix'), 9, 3);
24
+ }
25
 
26
  // URI Editor
27
  add_filter('permalink-manager-uri-editor-extra-info', array($this, 'wpml_lang_column_content_uri_editor'), 9, 3);
28
 
29
+ if((isset($sitepress_settings['language_negotiation_type']) && in_array($sitepress_settings['language_negotiation_type'], array(1, 2))) || (isset($polylang->links_model->options['force_lang']) && in_array($polylang->links_model->options['force_lang'], array(1, 3)))) {
30
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_detect_post'), 9, 3);
31
+ add_filter('permalink_manager-filter-permalink-base', array($this, 'wpml_append_lang_prefix'), 9, 2);
 
32
  add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 );
33
  } else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) {
34
  add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9);
81
  }
82
  }
83
 
84
+ /**
85
+ * 0. Stop redirect
86
+ */
87
+ public static function stop_redirect() {
88
+ global $wp_query;
89
+
90
+ if(!empty($wp_query->query)) {
91
+ $query_vars = $wp_query->query;
92
+
93
+ // WordPress Photo Seller Plugin
94
+ if(!empty($query_vars['image_id']) && !empty($query_vars['gallery_id'])) {
95
+ $wp_query->query_vars['do_not_redirect'] = 1;
96
+ }
97
+ }
98
+ }
99
+
100
  /**
101
  * 1. WPML filters
102
  */
103
+ public static function wpml_get_language_code($element) {
104
+ if(isset($element->post_type)) {
105
+ $element_id = $element->ID;
106
+ $element_type = $element->post_type;
107
+ } else if(isset($element->taxonomy)) {
108
+ $element_id = $element->term_taxonomy_id;
109
+ $element_type = $element->taxonomy;
110
+ } else {
111
+ return false;
112
+ }
113
+
114
+ $lang_code = apply_filters('wpml_element_language_code', null, array('element_id' => $element_id, 'element_type' => $element_type));
115
+
116
+ // Use default language if nothing detected
117
+ return ($lang_code) ? $lang_code : self::get_default_language();
118
+ }
119
+
120
+ public static function get_default_language() {
121
+ global $sitepress;
122
+
123
+ if(function_exists('pll_default_language')) {
124
+ $def_lang = pll_default_language('slug');
125
+ } else if(is_object($sitepress)) {
126
+ $def_lang = $sitepress->get_default_language();
127
+ } else {
128
+ $def_lang = '';
129
+ }
130
+
131
+ return $def_lang;
132
+ }
133
+
134
  function wpml_language_mismatch_fix($item_id, $uri_parts, $is_term = false) {
135
  global $wp, $language_code;
136
 
138
  $element = get_term($item_id);
139
  if(!empty($element) && !is_wp_error($element)) {
140
  $element_id = $element->term_taxonomy_id;
 
141
  } else {
142
  return false;
143
  }
144
  } else {
145
+ $element = get_post($item_id);
146
+
147
+ if(!empty($element->post_type)) {
148
+ $element_type = $element->post_type;
149
+ $element_id = $item_id;
150
+ }
151
  }
152
 
153
  // Stop if no term or post is detected
154
+ if(empty($element)) { return false; }
155
 
156
+ $language_code = self::wpml_get_language_code($element);
157
 
158
  if(!empty($uri_parts['lang']) && ($uri_parts['lang'] != $language_code)) {
159
  $wpml_item_id = apply_filters('wpml_object_id', $element_id);
175
  $default_language = pll_default_language();
176
  }
177
 
178
+ // Fix for multidomain language configuration
179
+ if(!empty($polylang->options['force_lang']) && $polylang->options['force_lang'] == 3) {
180
+ $domains = (array) $polylang->options['domains'];
181
+
182
+ foreach($domains as &$domain) {
183
+ $domain = preg_replace("/http(s)?:\/\/(www\.)?(.+?)\/?$/", "http://$3", $domain);
184
+ }
185
+
186
+ $request_url = trim(str_replace($domains, "", $request_url), "/");
187
+ }
188
+
189
  if(!empty($languages_list)) {
190
+ //preg_match("/^(?:({$languages_list})\/)?(.+?)(?|\/({$endpoints})[\/$]([^\/]*)|\/()([\d+]))?\/?$/i", $request_url, $regex_parts);
191
+ preg_match("/^(?:({$languages_list})\/)?(.+?)(?|\/({$endpoints})(?|\/(.*)|$)|\/()([\d]+)\/?)?$/i", $request_url, $regex_parts);
192
 
193
  $uri_parts['lang'] = (!empty($regex_parts[1])) ? $regex_parts[1] : $default_language;
194
  $uri_parts['uri'] = (!empty($regex_parts[2])) ? $regex_parts[2] : "";
199
  return $uri_parts;
200
  }
201
 
202
+ function wpml_append_lang_prefix($base, $element) {
203
+ global $sitepress_settings, $polylang, $permalink_manager_uris;
204
 
205
+ $language_code = self::wpml_get_language_code($element);
206
+ $default_language_code = self::get_default_language();
 
 
 
 
 
 
 
207
 
208
+ // Last instance - use language paramater from &_GET array
209
+ if(is_admin()) {
 
 
210
  $language_code = (empty($language_code) && !empty($_GET['lang'])) ? $_GET['lang'] : $language_code;
211
  }
212
 
213
+ // Adjust URL base
214
  if(!empty($language_code)) {
215
+ // A. Different domain per language
216
+ if((isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 2) || (!empty($polylang->options['force_lang']) && $polylang->options['force_lang'] == 3)) {
217
+ if(!empty($polylang->options['domains'])) {
218
+ $domains = $polylang->options['domains'];
219
+ } else if(!empty($sitepress_settings['language_domains'])) {
220
+ $domains = $sitepress_settings['language_domains'];
221
+ }
222
+
223
+ $is_term = (!empty($element->term_taxonomy_id)) ? true : false;
224
+ $element_id = ($is_term) ? "tax-{$element->term_taxonomy_id}" : $element->ID;
225
 
226
+ // Filter only custom permalinks
227
+ if(empty($permalink_manager_uris[$element_id]) || empty($domains)) { return $base; }
 
228
 
229
+ // Replace the domain name
230
+ if(!empty($domains[$language_code])) {
231
+ $base = trim($domains[$language_code], "/");
232
+
233
+ // Append URL scheme
234
+ if(!preg_match("~^(?:f|ht)tps?://~i", $base)) {
235
+ $home_url = get_home_url();
236
+ $scehme = parse_url($home_url, PHP_URL_SCHEME);
237
+ $base = "{$scehme}://{$base}";
238
+ }
239
+ }
240
+ }
241
+ // B. Append prefix
242
+ else {
243
+ // Hide language code if "Use directory for default language" option is enabled
244
+ $hide_prefix_for_default_lang = ((isset($sitepress_settings['urls']['directory_for_default_language']) && $sitepress_settings['urls']['directory_for_default_language'] != 1) || !empty($polylang->links_model->options['hide_default'])) ? true : false;
245
+
246
+ if($hide_prefix_for_default_lang && ($default_language_code == $language_code)) {
247
+ return $base;
248
+ } else {
249
+ $base .= "/{$language_code}";
250
+ }
251
  }
252
  }
253
 
254
+ return $base;
255
  }
256
 
257
  function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) {
 
 
 
 
258
  $post = (is_integer($element)) ? get_post($element) : $element;
259
+ $language_code = self::wpml_get_language_code($post);
260
+
261
+ $post_type_slug = apply_filters('wpml_get_translated_slug', $post_type_slug, $post_type, $language_code);
262
 
263
  // Translate %post_type% tag in custom permastructures
264
+ return $post_type_slug;
265
  }
266
 
267
  function wpml_lang_column_uri_editor($columns) {
273
  }
274
 
275
  function wpml_lang_column_content_uri_editor($output, $column, $element) {
276
+ $language_code = self::wpml_get_language_code($element);
 
 
 
 
 
 
 
 
 
 
277
  $output .= (!empty($language_code)) ? sprintf(" | <span><strong>%s:</strong> %s</span>", __("Language"), $language_code) : "";
278
 
279
  return $output;
305
  $amp_query_var = AMP_QUERY_VAR;
306
 
307
  // Check if AMP should be triggered
308
+ preg_match("/^(.+?)\/({$amp_query_var})?\/?$/i", $uri_parts['uri'], $regex_parts);
309
  if(!empty($regex_parts[2])) {
310
  $uri_parts['uri'] = $regex_parts[1];
311
  $amp_enabled = true;
includes/core/permalink-manager-uri-functions-post.php CHANGED
@@ -51,7 +51,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
51
  $post = (is_integer($post)) ? get_post($post) : $post;
52
 
53
  // Start with homepage URL
54
- $home_url = trim(get_option('home'), "/");
55
 
56
  // 1. Check if post type is allowed
57
  if(!empty($post->post_type) && Permalink_Manager_Helper_Functions::is_disabled($post->post_type, 'post_type')) { return $permalink; }
@@ -70,14 +70,11 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
70
 
71
  // 4. Filter only the posts with custom permalink assigned
72
  if(isset($permalink_manager_uris[$post->ID])) {
73
- // Apend the language code as a non-editable prefix (can be used also for another prefixes)
74
- $prefix = apply_filters('permalink-manager-post-permalink-prefix', '', $post);
75
-
76
  // Encode URI?
77
  if(!empty($permalink_manager_options['general']['decode_uris'])) {
78
- $permalink = "{$home_url}/" . urldecode("/{$prefix}{$permalink_manager_uris[$post->ID]}");
79
  } else {
80
- $permalink = "{$home_url}/" . Permalink_Manager_Helper_Functions::encode_uri("{$prefix}{$permalink_manager_uris[$post->ID]}");
81
  }
82
  } else if($post->post_type == 'attachment' && $post->post_parent > 0 && $post->post_parent != $post->ID && !empty($permalink_manager_uris[$post->post_parent])) {
83
  $permalink = "{$home_url}/{$permalink_manager_uris[$post->post_parent]}/attachment/{$post->post_name}";
@@ -98,7 +95,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
98
  global $wpdb;
99
 
100
  // Update slug and make it unique
101
- $slug = (empty($slug)) ? Permalink_Manager_Helper_Functions::sanitize_title(get_the_title($id)) : $slug;
 
 
102
  $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
103
  $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
104
 
@@ -173,15 +172,30 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
173
  }
174
  $post_type_slug = apply_filters('permalink_manager_filter_post_type_slug', $post_type_slug, $post, $post_type);
175
 
 
 
 
 
 
176
  // 3A. Fix for hierarchical CPT (start)
177
- $full_slug = (is_post_type_hierarchical($post_type)) ? get_page_uri($post) : $post_name;
178
- $full_slug = (empty($full_slug)) ? $post_name : $full_slug;
 
 
 
 
 
 
 
 
179
 
180
- // 3B. Allow filter the default slug
181
  if(!$native_uri) {
182
- $full_slug = ($native_uri) ? $full_slug : Permalink_Manager_Helper_Functions::force_custom_slugs($full_slug, $post);
183
- $full_slug = apply_filters('permalink_manager_filter_default_post_slug', $full_slug, $post, $post_name);
 
184
  }
 
185
  $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
186
 
187
  // 3C. Get the standard tags and replace them with their values
@@ -192,8 +206,6 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
192
  // 3D. Check if any post tag is present in custom permastructure
193
  $do_not_append_slug = apply_filters("permalink_manager_do_not_append_slug", false, $post_type, $post);
194
  if($do_not_append_slug == false) {
195
- $slug_tags = array($post_type_tag, '%postname%', '%postname_flat%');
196
- $slug_tags_replacement = array($full_slug, $full_slug, $post_name);
197
  foreach($slug_tags as $tag) {
198
  if(strpos($default_uri, $tag) !== false) {
199
  $do_not_append_slug = true;
@@ -202,74 +214,64 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
202
  }
203
  }
204
 
205
- // 3E. Replace the post tags with slugs or rppend the slug if no post tag is defined
206
- if(!empty($do_not_append_slug)) {
207
- $default_uri = str_replace($slug_tags, $slug_tags_replacement, $default_uri);
208
- } else {
 
 
 
209
  $default_uri .= "/{$full_slug}";
210
  }
211
 
212
- // 3C. Replace taxonomies
213
  $taxonomies = get_taxonomies();
214
 
215
  if($taxonomies) {
216
  foreach($taxonomies as $taxonomy) {
217
  // 1. Reset $replacement
218
- $replacement = $terms = $replacement_term = "";
 
219
 
220
  // 2. Try to use Yoast SEO Primary Term
221
  $replacement_term = $primary_term = Permalink_Manager_Helper_Functions::get_primary_term($post->ID, $taxonomy, false);
222
 
223
  // 3. Get the first assigned term to this taxonomy
224
  if(empty($replacement_term)) {
225
- $terms = wp_get_object_terms($post->ID, $taxonomy);
226
- $replacement_term = (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) ? $terms[0] : "";
227
  $replacement_term = apply_filters('permalink_manager_filter_post_terms', $replacement_term, $post, $terms, $taxonomy, $native_uri);
228
  }
229
 
230
- // 4A. Get permalink base from the term's custom URI
231
  if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_custom_uri%") !== false && !empty($permalink_manager_uris["tax-{$replacement_term->term_id}"])) {
232
- $replacement = $permalink_manager_uris["tax-{$replacement_term->term_id}"];
233
  }
234
- // 4B. Hierarhcical taxonomy base
235
  else if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_flat%") === false && is_taxonomy_hierarchical($taxonomy)) {
236
- $ancestors = get_ancestors( $replacement_term->term_id, $taxonomy, 'taxonomy' );
237
- $hierarchical_slugs = array();
238
-
239
- foreach((array) $ancestors as $ancestor) {
240
- $ancestor_term = get_term($ancestor, $taxonomy);
241
- $hierarchical_slugs[] = ($native_uri) ? $replacement_term->slug : Permalink_Manager_Helper_Functions::force_custom_slugs($ancestor_term->slug, $ancestor_term);
242
- }
243
- $hierarchical_slugs = array_reverse($hierarchical_slugs);
244
- $replacement = implode('/', $hierarchical_slugs);
245
-
246
- // Append the term slug now
247
- $last_term_slug = ($native_uri) ? $replacement_term->slug : Permalink_Manager_Helper_Functions::force_custom_slugs($replacement_term->slug, $replacement_term);
248
- $replacement = "{$replacement}/{$last_term_slug}";
249
  }
250
- // 4C. Force flat taxonomy base - get highgest level term (if %taxonomy_flat% tag is used)
251
  else if(!$native_uri && strpos($default_uri, "%{$taxonomy}_flat%") !== false && !empty($terms) && empty($primary_term->slug)) {
252
- foreach ($terms as $single_term) {
253
- if ($single_term->parent == 0) {
254
- $replacement = Permalink_Manager_Helper_Functions::force_custom_slugs($single_term->slug, $single_term);
255
- break;
256
- }
257
- }
258
  }
259
- // 4D. Flat/non-hierarchical taxonomy base - get primary term (if set) or first term
260
- else if(!empty($replacement_term->slug)) {
261
- $replacement = ($native_uri) ? $replacement_term->slug : Permalink_Manager_Helper_Functions::force_custom_slugs($replacement_term->slug, $replacement_term);
262
  }
263
 
 
 
 
 
264
  // Filter final category slug
265
  $replacement = apply_filters('permalink_manager_filter_term_slug', $replacement, $replacement_term, $post, $terms, $taxonomy, $native_uri);
266
 
267
  // 4. Do the replacement
268
- $default_uri = (!empty($replacement)) ? str_replace(array("%{$taxonomy}%", "%{$taxonomy}_flat%", "%{$taxonomy}_custom_uri%"), $replacement, $default_uri) : $default_uri;
269
  }
270
  }
271
 
272
- // 4. Clear the URI
273
  $default_uri = preg_replace('/\s+/', '', $default_uri);
274
  $default_uri = str_replace('//', '/', $default_uri);
275
  $default_uri = trim($default_uri, "/");
@@ -283,7 +285,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
283
  function exclude_homepage($uris) {
284
  // Find the homepage URI
285
  $homepage_id = get_option('page_on_front');
286
- if(isset($uris[$homepage_id])) { unset($uris[$homepage_id]); }
287
 
288
  return $uris;
289
  }
@@ -298,7 +300,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
298
  if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
299
 
300
  // Get homepage URL and ensure that it ends with slash
301
- $home_url = trim(get_option('home'), "/") . "/";
302
 
303
  // Reset variables
304
  $updated_slugs_count = 0;
@@ -442,6 +444,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
442
  // Support for attachments
443
  if(in_array('attachment', $post_types_array)) {
444
  $attachment_support = " OR (post_type = 'attachment')";
 
 
445
  }
446
 
447
  // Get the rows before they are altered
@@ -458,7 +462,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
458
  $default_uri = self::get_default_post_uri($row['ID']);
459
  $old_post_name = $row['post_name'];
460
  $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
461
- $correct_slug = Permalink_Manager_Helper_Functions::sanitize_title($row['post_title']);
462
 
463
  // Process URI & slug
464
  $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
@@ -473,7 +477,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
473
  $new_uri = $default_uri;
474
  }
475
 
476
- //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n");
477
 
478
  // Check if native slug should be changed
479
  if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
@@ -576,8 +580,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
576
  $native_uri = self::get_default_post_uri($id, true);
577
 
578
  // Make sure that home URL ends with slash
579
- $home_url = trim(get_option('home'), "/") . "/";
580
- $prefix = apply_filters('permalink-manager-post-permalink-prefix', '', $post, true);
581
 
582
  // Do not change anything if post is not saved yet (display sample permalink instead)
583
  if(get_option('page_on_front') == $id) {
@@ -593,16 +596,16 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
593
  $sample_permalink_url = apply_filters('permalink_manager_filter_post_sample_permalink', urldecode($sample_permalink_url), $post);
594
 
595
  // Prepare the sample & default permalink
596
- $sample_permalink = sprintf("{$home_url}{$prefix}<span class=\"editable\">%s</span>", str_replace("//", "/", $sample_permalink_url));
597
 
598
  // Allow to filter the sample permalink URL
599
 
600
  // Append new HTML output
601
- $html .= sprintf("<span class=\"sample-permalink-span\"><a href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
602
- $html .= (!$autosave) ? Permalink_Manager_Admin_Functions::display_uri_box($post, $default_uri, $uri, $native_uri, "{$home_url}{$prefix}") : "";
603
 
604
  // Append hidden field with native slug
605
- $html .= (!empty($post->post_name)) ? "<input id=\"new-post-slug\" value=\"{$post->post_name}\" autocomplete=\"off\" type=\"hidden\">" : "";
606
 
607
  return $html;
608
  }
@@ -617,7 +620,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
617
  $post_type = (!empty($current_screen->post_type)) ? $current_screen->post_type : false;
618
 
619
  // Check if post type is disabled
620
- if(Permalink_Manager_Helper_Functions::is_disabled($post_type, 'post_type')) { return $columns; }
621
 
622
  return array_merge($columns, array('permalink-manager-col' => __( 'Current URI', 'permalink-manager')));
623
  }
@@ -637,8 +640,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
637
  }
638
 
639
  /**
640
- * Update URI when new post is added
641
- */
642
  function new_post_uri($post_id) {
643
  global $post, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
644
 
@@ -646,7 +649,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
646
  if(wp_is_post_revision($post_id)) { return $post_id; }
647
 
648
  // Prevent language mismatch in MultilingualPress plugin
649
- if(!empty($post->ID) && $post->ID != $post_id) { return $post_id; }
650
 
651
  // Do not do anything if post is autosaved
652
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
51
  $post = (is_integer($post)) ? get_post($post) : $post;
52
 
53
  // Start with homepage URL
54
+ $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post);
55
 
56
  // 1. Check if post type is allowed
57
  if(!empty($post->post_type) && Permalink_Manager_Helper_Functions::is_disabled($post->post_type, 'post_type')) { return $permalink; }
70
 
71
  // 4. Filter only the posts with custom permalink assigned
72
  if(isset($permalink_manager_uris[$post->ID])) {
 
 
 
73
  // Encode URI?
74
  if(!empty($permalink_manager_options['general']['decode_uris'])) {
75
+ $permalink = "{$home_url}/" . urldecode("/{$permalink_manager_uris[$post->ID]}");
76
  } else {
77
+ $permalink = "{$home_url}/" . Permalink_Manager_Helper_Functions::encode_uri("{$permalink_manager_uris[$post->ID]}");
78
  }
79
  } else if($post->post_type == 'attachment' && $post->post_parent > 0 && $post->post_parent != $post->ID && !empty($permalink_manager_uris[$post->post_parent])) {
80
  $permalink = "{$home_url}/{$permalink_manager_uris[$post->post_parent]}/attachment/{$post->post_name}";
95
  global $wpdb;
96
 
97
  // Update slug and make it unique
98
+ $slug = (empty($slug)) ? get_the_title($id) : $slug;
99
+ $slug = sanitize_title($slug);
100
+
101
  $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
102
  $wpdb->query("UPDATE $wpdb->posts SET post_name = '$new_slug' WHERE ID = '$id'");
103
 
172
  }
173
  $post_type_slug = apply_filters('permalink_manager_filter_post_type_slug', $post_type_slug, $post, $post_type);
174
 
175
+ // 3B. Get the full slug
176
+ $custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post);
177
+ $full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post);
178
+ $full_native_slug = $post_name;
179
+
180
  // 3A. Fix for hierarchical CPT (start)
181
+ // $full_slug = (is_post_type_hierarchical($post_type)) ? get_page_uri($post) : $post_name;
182
+ if($post->ancestors) {
183
+ foreach($post->ancestors as $parent) {
184
+ $parent = get_post($parent);
185
+ if($parent && $parent->post_name) {
186
+ $full_native_slug = $parent->post_name . '/' . $full_native_slug;
187
+ $full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($parent->post_name, $parent) . '/' . $full_custom_slug;
188
+ }
189
+ }
190
+ }
191
 
192
+ // 3B. Allow filter the default slug (only custom permalinks)
193
  if(!$native_uri) {
194
+ $full_slug = apply_filters('permalink_manager_filter_default_post_slug', $full_custom_slug, $post, $post_name);
195
+ } else {
196
+ $full_slug = $full_native_slug;
197
  }
198
+
199
  $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
200
 
201
  // 3C. Get the standard tags and replace them with their values
206
  // 3D. Check if any post tag is present in custom permastructure
207
  $do_not_append_slug = apply_filters("permalink_manager_do_not_append_slug", false, $post_type, $post);
208
  if($do_not_append_slug == false) {
 
 
209
  foreach($slug_tags as $tag) {
210
  if(strpos($default_uri, $tag) !== false) {
211
  $do_not_append_slug = true;
214
  }
215
  }
216
 
217
+ // 3E. Get the slug tags & do the replacement
218
+ $slug_tags = array($post_type_tag, '%postname%', '%postname_flat%', '%native_slug%');
219
+ $slug_tags_replacement = array($full_slug, $full_slug, $custom_slug, $full_native_slug);
220
+ $default_uri = str_replace($slug_tags, $slug_tags_replacement, $default_uri);
221
+
222
+ // 3F. Replace the post tags with slugs or rppend the slug if no post tag is defined
223
+ if(empty($do_not_append_slug)) {
224
  $default_uri .= "/{$full_slug}";
225
  }
226
 
227
+ // 4. Replace taxonomies
228
  $taxonomies = get_taxonomies();
229
 
230
  if($taxonomies) {
231
  foreach($taxonomies as $taxonomy) {
232
  // 1. Reset $replacement
233
+ $replacement = $replacement_term = "";
234
+ $terms = wp_get_object_terms($post->ID, $taxonomy);
235
 
236
  // 2. Try to use Yoast SEO Primary Term
237
  $replacement_term = $primary_term = Permalink_Manager_Helper_Functions::get_primary_term($post->ID, $taxonomy, false);
238
 
239
  // 3. Get the first assigned term to this taxonomy
240
  if(empty($replacement_term)) {
241
+ $replacement_term = (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) ? Permalink_Manager_Helper_Functions::get_lowest_element($terms[0], $terms) : "";
 
242
  $replacement_term = apply_filters('permalink_manager_filter_post_terms', $replacement_term, $post, $terms, $taxonomy, $native_uri);
243
  }
244
 
245
+ // 4A. Custom URI as term base
246
  if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_custom_uri%") !== false && !empty($permalink_manager_uris["tax-{$replacement_term->term_id}"])) {
247
+ $mode = 1;
248
  }
249
+ // 4B. Hierarhcical term base
250
  else if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_flat%") === false && is_taxonomy_hierarchical($taxonomy)) {
251
+ $mode = 2;
 
 
 
 
 
 
 
 
 
 
 
 
252
  }
253
+ // 4C. Force flat term base - get highgest level term (if %taxonomy_flat% tag is used)
254
  else if(!$native_uri && strpos($default_uri, "%{$taxonomy}_flat%") !== false && !empty($terms) && empty($primary_term->slug)) {
255
+ $mode = 3;
 
 
 
 
 
256
  }
257
+ // 4D. Flat/non-hierarchical term base - get primary term (if set) or first term
258
+ else {
259
+ $mode = 4;
260
  }
261
 
262
+ // Get the replacement slug (custom + native)
263
+ $replacement = Permalink_Manager_Helper_Functions::get_term_full_slug($replacement_term, $terms, $mode, $native_uri);
264
+ $native_replacement = Permalink_Manager_Helper_Functions::get_term_full_slug($replacement_term, $terms, $mode, true);
265
+
266
  // Filter final category slug
267
  $replacement = apply_filters('permalink_manager_filter_term_slug', $replacement, $replacement_term, $post, $terms, $taxonomy, $native_uri);
268
 
269
  // 4. Do the replacement
270
+ $default_uri = (!empty($replacement)) ? str_replace(array("%{$taxonomy}%", "%{$taxonomy}_flat%", "%{$taxonomy}_custom_uri%", "%{$taxonomy}_native_slug%"), array($replacement, $replacement, $replacement, $native_replacement), $default_uri) : $default_uri;
271
  }
272
  }
273
 
274
+ // 5. Clear the URI
275
  $default_uri = preg_replace('/\s+/', '', $default_uri);
276
  $default_uri = str_replace('//', '/', $default_uri);
277
  $default_uri = trim($default_uri, "/");
285
  function exclude_homepage($uris) {
286
  // Find the homepage URI
287
  $homepage_id = get_option('page_on_front');
288
+ if(is_array($uris) && !empty($uris[$homepage_id])) { unset($uris[$homepage_id]); }
289
 
290
  return $uris;
291
  }
300
  if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
301
 
302
  // Get homepage URL and ensure that it ends with slash
303
+ $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post) . "/";
304
 
305
  // Reset variables
306
  $updated_slugs_count = 0;
444
  // Support for attachments
445
  if(in_array('attachment', $post_types_array)) {
446
  $attachment_support = " OR (post_type = 'attachment')";
447
+ } else {
448
+ $attachment_support = "";
449
  }
450
 
451
  // Get the rows before they are altered
462
  $default_uri = self::get_default_post_uri($row['ID']);
463
  $old_post_name = $row['post_name'];
464
  $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri;
465
+ $correct_slug = ($mode == 'slugs') ? sanitize_title($row['post_title']) : Permalink_Manager_Helper_Functions::sanitize_title($row['post_title']);
466
 
467
  // Process URI & slug
468
  $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
477
  $new_uri = $default_uri;
478
  }
479
 
480
+ //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} / - {$new_slug} - {$new_post_name} \n");
481
 
482
  // Check if native slug should be changed
483
  if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
580
  $native_uri = self::get_default_post_uri($id, true);
581
 
582
  // Make sure that home URL ends with slash
583
+ $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post);
 
584
 
585
  // Do not change anything if post is not saved yet (display sample permalink instead)
586
  if(get_option('page_on_front') == $id) {
596
  $sample_permalink_url = apply_filters('permalink_manager_filter_post_sample_permalink', urldecode($sample_permalink_url), $post);
597
 
598
  // Prepare the sample & default permalink
599
+ $sample_permalink = sprintf("{$home_url}/<span class=\"editable\">%s</span>", str_replace("//", "/", $sample_permalink_url));
600
 
601
  // Allow to filter the sample permalink URL
602
 
603
  // Append new HTML output
604
+ $html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
605
+ $html .= (!$autosave) ? Permalink_Manager_Admin_Functions::display_uri_box($post, $default_uri, $uri, $native_uri) : "";
606
 
607
  // Append hidden field with native slug
608
+ // $html .= (!empty($post->post_name)) ? "<input id=\"new-post-slug\" value=\"{$post->post_name}\" autocomplete=\"off\" type=\"hidden\">" : "";
609
 
610
  return $html;
611
  }
620
  $post_type = (!empty($current_screen->post_type)) ? $current_screen->post_type : false;
621
 
622
  // Check if post type is disabled
623
+ if($post_type && Permalink_Manager_Helper_Functions::is_disabled($post_type, 'post_type')) { return $columns; }
624
 
625
  return array_merge($columns, array('permalink-manager-col' => __( 'Current URI', 'permalink-manager')));
626
  }
640
  }
641
 
642
  /**
643
+ * Update URI when new post is added
644
+ */
645
  function new_post_uri($post_id) {
646
  global $post, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
647
 
649
  if(wp_is_post_revision($post_id)) { return $post_id; }
650
 
651
  // Prevent language mismatch in MultilingualPress plugin
652
+ if(is_admin() && !empty($post->ID) && $post->ID != $post_id) { return $post_id; }
653
 
654
  // Do not do anything if post is autosaved
655
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
includes/views/permalink-manager-settings.php CHANGED
@@ -94,10 +94,17 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
94
  'input_class' => '',
95
  'description' => sprintf(__('If enabled, the custom URIs assigned to removed posts & terms will be automatically removed.<br />To manually remove the duplicates please go <a href="%s">to this page</a>.', 'permalink-manager'), admin_url('tools.php?page=permalink-manager&section=tools&subsection=duplicates'))
96
  ),
97
- 'force_custom_slugs' => array(
98
  'type' => 'single_checkbox',
99
- 'label' => __('Force custom slugs', 'permalink-manager'),
100
  'input_class' => '',
 
 
 
 
 
 
 
101
  'description' => __('If enabled, the slugs in the default custom permalinks will be recreated from the post titles.<br />This may cause permalinks duplicates when the post or term title is used more than once.', 'permalink-manager')
102
  ),
103
  'partial_disable' => array(
94
  'input_class' => '',
95
  'description' => sprintf(__('If enabled, the custom URIs assigned to removed posts & terms will be automatically removed.<br />To manually remove the duplicates please go <a href="%s">to this page</a>.', 'permalink-manager'), admin_url('tools.php?page=permalink-manager&section=tools&subsection=duplicates'))
96
  ),
97
+ 'fix_language_mismatch' => array(
98
  'type' => 'single_checkbox',
99
+ 'label' => __('Fix language mismatch', 'permalink-manager'),
100
  'input_class' => '',
101
+ 'description' => __('If enabled, the plugin will load the adjacent translation of post when the custom permalink is detected, but the language code in the URL does not match the language code assigned to the post/term.', 'permalink-manager')
102
+ ),
103
+ 'force_custom_slugs' => array(
104
+ 'type' => 'select',
105
+ 'label' => __('Force custom slugs', 'permalink-manager'),
106
+ 'input_class' => 'settings-select',
107
+ 'choices' => array(0 => __('No, use native slugs', 'permalink-manager'), 1 => __('Yes, use post/term titles', 'permalink-manager'), 2 => __('Yes, use post/term titles + do not strip special characters: .|-+', 'permalink-manager')),
108
  'description' => __('If enabled, the slugs in the default custom permalinks will be recreated from the post titles.<br />This may cause permalinks duplicates when the post or term title is used more than once.', 'permalink-manager')
109
  ),
110
  'partial_disable' => array(
out/permalink-manager-admin.css CHANGED
@@ -98,15 +98,16 @@
98
  #permalink-manager.permalink-manager-edit-uri-box .strong{display:block;font-weight:bold;margin-bottom:5px}
99
  #permalink-manager.permalink-manager-edit-uri-box .toggle-indicator:before{content:"\f142";display:inline-block;font:400 20px/1 dashicons}
100
  #permalink-manager.permalink-manager-edit-uri-box .columns-container{margin-left:-10px!important;margin-right:-10px!important}
101
- #permalink-manager.permalink-manager-edit-uri-box .columns-container > *{padding-left:10px!important;padding-right:10px!important}
102
  #permalink-manager.permalink-manager-edit-uri-box .close-button{float:right;width:36px;height:36px;padding:0;cursor:pointer;display:block}
103
  #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}
104
  #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}
105
  #permalink-manager .default-permalink-row,#permalink-manager .redirects-row{border-top:1px solid #eee;padding-top:10px}
 
106
  #permalink-manager .default-permalink-row,#permalink-manager .default-permastruct-row,#permalink-manager .redirects-row{color:#aaa;font-size:90%}
107
  #permalink-manager .restore-default{display:inline-block;text-align:right;width:100%;border-radius:0;color:#959595;text-decoration:none}
108
  #permalink-manager .widefat,#permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside table{width:100%!important}
109
- #permalink-manager .heading,#permalink-manager .heading a{margin:0;line-height:1.4;font-weight:600;text-decoration:none}
110
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box{display:block!important;margin:0}
111
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box h2,.permalink-manager.postbox .heading{font-size:14px!important;padding:8px 12px;margin:0;line-height:1.4}
112
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box .close-button,#permalink-manager.permalink-manager-edit-term #permalink-manager-toggle{display:none}
@@ -129,6 +130,8 @@
129
  .permalink-manager #redirect-panel-inside table{margin-bottom:10px}
130
  .permalink-manager #redirect-panel-inside table td{padding:5px 0;width:100%}
131
  .permalink-manager #redirect-panel-inside table td a{text-decoration:none;text-align:right}
 
 
132
  .permalink-manager .sample-row{display:none}
133
  .permalink-manager .redirects-panel-description{margin-bottom:10px}
134
  .permalink-manager .redirects-panel-description *{font-size:12px}
98
  #permalink-manager.permalink-manager-edit-uri-box .strong{display:block;font-weight:bold;margin-bottom:5px}
99
  #permalink-manager.permalink-manager-edit-uri-box .toggle-indicator:before{content:"\f142";display:inline-block;font:400 20px/1 dashicons}
100
  #permalink-manager.permalink-manager-edit-uri-box .columns-container{margin-left:-10px!important;margin-right:-10px!important}
101
+ #permalink-manager.permalink-manager-edit-uri-box .columns-container > *{padding-left:10px;padding-right:10px}
102
  #permalink-manager.permalink-manager-edit-uri-box .close-button{float:right;width:36px;height:36px;padding:0;cursor:pointer;display:block}
103
  #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}
104
  #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}
105
  #permalink-manager .default-permalink-row,#permalink-manager .redirects-row{border-top:1px solid #eee;padding-top:10px}
106
+ #permalink-manager .redirects-row{border-top:3px double #eee;padding-top:10px}
107
  #permalink-manager .default-permalink-row,#permalink-manager .default-permastruct-row,#permalink-manager .redirects-row{color:#aaa;font-size:90%}
108
  #permalink-manager .restore-default{display:inline-block;text-align:right;width:100%;border-radius:0;color:#959595;text-decoration:none}
109
  #permalink-manager .widefat,#permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside table{width:100%!important}
110
+ #permalink-manager .heading,#permalink-manager .heading a{margin:0;line-height:1.4;font-weight:600;text-decoration:none;color:#777}
111
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box{display:block!important;margin:0}
112
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box h2,.permalink-manager.postbox .heading{font-size:14px!important;padding:8px 12px;margin:0;line-height:1.4}
113
  #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box .close-button,#permalink-manager.permalink-manager-edit-term #permalink-manager-toggle{display:none}
130
  .permalink-manager #redirect-panel-inside table{margin-bottom:10px}
131
  .permalink-manager #redirect-panel-inside table td{padding:5px 0;width:100%}
132
  .permalink-manager #redirect-panel-inside table td a{text-decoration:none;text-align:right}
133
+ .permalink-manager #redirect-panel-inside .single-section{margin-left:-10px;margin-right:-10px;padding:10px;border-top:1px dashed #eee}
134
+ .permalink-manager #redirect-panel-inside .single-section:last-of-type{padding-bottom:0}
135
  .permalink-manager .sample-row{display:none}
136
  .permalink-manager .redirects-panel-description{margin-bottom:10px}
137
  .permalink-manager .redirects-panel-description *{font-size:12px}
out/permalink-manager-admin.js CHANGED
@@ -112,7 +112,11 @@ jQuery(document).ready(function() {
112
  }
113
  });
114
 
115
- function permalink_manager_duplicate_check(custom_uri_input = false, multi = false) {
 
 
 
 
116
  var all_custom_uris_values = {};
117
 
118
  if(custom_uri_input) {
112
  }
113
  });
114
 
115
+ function permalink_manager_duplicate_check(custom_uri_input, multi) {
116
+ // Set default values
117
+ custom_uri_input = typeof custom_uri_input !== 'undefined' ? custom_uri_input : false;
118
+ multi = typeof multi !== 'undefined' ? multi : false;
119
+
120
  var all_custom_uris_values = {};
121
 
122
  if(custom_uri_input) {
permalink-manager.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: Permalink Manager Lite
5
  * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6
  * Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
7
- * Version: 2.0.5.8
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
@@ -21,7 +21,7 @@ if (!defined('WPINC')) {
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24
- define( 'PERMALINK_MANAGER_VERSION', '2.0.5.8' );
25
  define( 'PERMALINK_MANAGER_FILE', __FILE__ );
26
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
27
  define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
@@ -118,12 +118,13 @@ class Permalink_Manager_Class {
118
  */
119
  public function get_options_and_globals() {
120
  // 1. Globals with data stored in DB
121
- global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $permalink_manager_redirects;
122
 
123
  $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager', array()));
124
  $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris', array()));
125
  $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
126
  $this->permalink_manager_redirects = $permalink_manager_redirects = apply_filters('permalink-manager-redirects', get_option('permalink-manager-redirects', array()));
 
127
 
128
  // 2. Globals used to display additional content (eg. alerts)
129
  global $permalink_manager_alerts, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
@@ -156,7 +157,8 @@ class Permalink_Manager_Class {
156
  'pagination_redirect' => 0,
157
  'auto_remove_duplicates' => 0,
158
  'partial_disable' => array(),
159
- 'deep_detect' => 1
 
160
  ),
161
  'licence' => array()
162
  ));
4
  * Plugin Name: Permalink Manager Lite
5
  * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6
  * Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
7
+ * Version: 2.0.6.2
8
  * Author: Maciej Bis
9
  * Author URI: http://maciejbis.net/
10
  * License: GPL-2.0+
21
  // Define the directories used to load plugin files.
22
  define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
23
  define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
24
+ define( 'PERMALINK_MANAGER_VERSION', '2.0.6.2' );
25
  define( 'PERMALINK_MANAGER_FILE', __FILE__ );
26
  define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
27
  define( 'PERMALINK_MANAGER_BASENAME', plugin_basename(__FILE__) );
118
  */
119
  public function get_options_and_globals() {
120
  // 1. Globals with data stored in DB
121
+ global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $permalink_manager_redirects, $permalink_manager_external_redirects;
122
 
123
  $this->permalink_manager_options = $permalink_manager_options = apply_filters('permalink-manager-options', get_option('permalink-manager', array()));
124
  $this->permalink_manager_uris = $permalink_manager_uris = apply_filters('permalink-manager-uris', get_option('permalink-manager-uris', array()));
125
  $this->permalink_manager_permastructs = $permalink_manager_permastructs = apply_filters('permalink-manager-permastructs', get_option('permalink-manager-permastructs', array()));
126
  $this->permalink_manager_redirects = $permalink_manager_redirects = apply_filters('permalink-manager-redirects', get_option('permalink-manager-redirects', array()));
127
+ $this->permalink_manager_external_redirects = $permalink_manager_external_redirects = apply_filters('permalink-manager-external-redirects', get_option('permalink-manager-external-redirects', array()));
128
 
129
  // 2. Globals used to display additional content (eg. alerts)
130
  global $permalink_manager_alerts, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
157
  'pagination_redirect' => 0,
158
  'auto_remove_duplicates' => 0,
159
  'partial_disable' => array(),
160
+ 'deep_detect' => 1,
161
+ 'fix_language_mismatch' => 1
162
  ),
163
  'licence' => array()
164
  ));