Premmerce Permalink Manager for WooCommerce - Version 2.1.3

Version Description

Release Date: Nov 14, 2018

  • Updated freemius version to 2.1.3
  • Added WooCommerce 3.5 support
Download this release

Release Info

Developer premmerce
Plugin Icon 128x128 Premmerce Permalink Manager for WooCommerce
Version 2.1.3
Comparing to
See all releases

Code changes from version 2.1.2 to 2.1.3

freemius/includes/class-freemius.php CHANGED
@@ -2630,26 +2630,28 @@
2630
  self::$_accounts = FS_Options::instance( WP_FS__ACCOUNTS_OPTION_NAME, true );
2631
 
2632
  if ( is_multisite() ) {
 
 
 
 
 
 
 
2633
  /**
2634
- * If the id_slug_type_path_map exists on the site level but doesn't exist on the
2635
  * network level storage, it means that we need to process the storage with migration.
2636
  *
2637
- * The code in this `if` scope will only be executed once and only for the first site that will execute it because once we migrate the storage data, id_slug_type_path_map will be already set in the network level storage.
2638
  *
2639
  * @author Vova Feldman (@svovaf)
2640
  * @since 2.0.0
2641
  */
2642
- if ( null === self::$_accounts->get_option( 'id_slug_type_path_map', null, true ) &&
2643
- null !== self::$_accounts->get_option( 'id_slug_type_path_map', null, false )
 
 
2644
  ) {
2645
- self::migrate_accounts_to_network();
2646
-
2647
- // Migrate API options from site level to network level.
2648
- $api_network_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true );
2649
- $api_network_options->migrate_to_network();
2650
-
2651
- // Migrate API cache to network level storage.
2652
- FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME )->migrate_to_network();
2653
  }
2654
  }
2655
 
@@ -2679,6 +2681,24 @@
2679
  self::$_statics_loaded = true;
2680
  }
2681
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2682
  #----------------------------------------------------------------------------------
2683
  #region Localization
2684
  #----------------------------------------------------------------------------------
@@ -2905,6 +2925,10 @@
2905
  }
2906
 
2907
  fs_redirect( $download_url );
 
 
 
 
2908
  }
2909
  }
2910
 
@@ -5987,7 +6011,7 @@
5987
  * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
5988
  */
5989
  private function schedule_install_sync( $except_blog_id = 0 ) {
5990
- $this->schedule_cron( 'install_sync', 'install_sync', 'single', 0, false, $except_blog_id );
5991
  }
5992
 
5993
  /**
@@ -10574,7 +10598,7 @@
10574
  return;
10575
  }
10576
 
10577
- if ( ! $this->is_premium() || $this->has_active_valid_license() ) {
10578
  // This is relevant only to the free versions and premium versions without an active license.
10579
  return;
10580
  }
@@ -15590,7 +15614,8 @@
15590
  return;
15591
  }
15592
 
15593
- $encrypted_site = clone ( is_object( $site ) ? $site : $this->_site );
 
15594
 
15595
  $sites = self::get_all_sites( $this->_module_type, $network_level_or_blog_id );
15596
 
@@ -16288,14 +16313,62 @@
16288
  * @since 1.2.1
16289
  */
16290
  function has_active_valid_license() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16291
  return (
16292
- is_object( $this->_license ) &&
16293
- is_numeric( $this->_license->id ) &&
16294
- $this->_license->is_active() &&
16295
- $this->_license->is_valid()
16296
  );
16297
  }
16298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16299
  /**
16300
  * Check if site assigned with license with enabled features.
16301
  *
@@ -17289,7 +17362,7 @@
17289
  * @return bool
17290
  */
17291
  private function _can_download_premium() {
17292
- return $this->has_active_valid_license() ||
17293
  ( $this->is_trial() && ! $this->get_trial_plan()->is_free() );
17294
  }
17295
 
@@ -18442,7 +18515,15 @@
18442
  $this->_logger->entrance();
18443
 
18444
  $vars = array( 'id' => $this->_module_id );
18445
- fs_require_once_template( 'contact.php', $vars );
 
 
 
 
 
 
 
 
18446
  }
18447
 
18448
  #endregion ------------------------------------------------------------------------
@@ -18748,14 +18829,14 @@
18748
 
18749
  // Show promotion if never shown before and 24 hours after initial activation with FS.
18750
  if ( ! $was_promotion_shown_before &&
18751
- $this->_storage->install_timestamp > ( time() - WP_FS__TIME_24_HOURS_IN_SEC )
18752
  ) {
18753
  return false;
18754
  }
18755
 
18756
  // OR if promotion was shown before, try showing it every 30 days.
18757
  if ( $was_promotion_shown_before &&
18758
- 30 * WP_FS__TIME_24_HOURS_IN_SEC > time() - $last_time_trial_promotion_shown
18759
  ) {
18760
  return false;
18761
  }
2630
  self::$_accounts = FS_Options::instance( WP_FS__ACCOUNTS_OPTION_NAME, true );
2631
 
2632
  if ( is_multisite() ) {
2633
+ $has_skipped_migration = (
2634
+ // 'id_slug_type_path_map' - was never stored on older versions, therefore, not exists on the site level.
2635
+ null === self::$_accounts->get_option( 'id_slug_type_path_map', null, false ) &&
2636
+ // 'file_slug_map' stored on the site level, so it was running an SDK version before it was integrated with MS-network.
2637
+ null !== self::$_accounts->get_option( 'file_slug_map', null, false )
2638
+ );
2639
+
2640
  /**
2641
+ * If the file_slug_map exists on the site level but doesn't exist on the
2642
  * network level storage, it means that we need to process the storage with migration.
2643
  *
2644
+ * The code in this `if` scope will only be executed once and only for the first site that will execute it because once we migrate the storage data, file_slug_map will be already set in the network level storage.
2645
  *
2646
  * @author Vova Feldman (@svovaf)
2647
  * @since 2.0.0
2648
  */
2649
+ if (
2650
+ ( $has_skipped_migration && true !== self::$_accounts->get_option( 'ms_migration_complete', false, true ) ) ||
2651
+ ( null === self::$_accounts->get_option( 'file_slug_map', null, true ) &&
2652
+ null !== self::$_accounts->get_option( 'file_slug_map', null, false ) )
2653
  ) {
2654
+ self::migrate_options_to_network();
 
 
 
 
 
 
 
2655
  }
2656
  }
2657
 
2681
  self::$_statics_loaded = true;
2682
  }
2683
 
2684
+ /**
2685
+ * @author Leo Fajardo (@leorw)
2686
+ *
2687
+ * @since 2.1.3
2688
+ */
2689
+ private static function migrate_options_to_network() {
2690
+ self::migrate_accounts_to_network();
2691
+
2692
+ // Migrate API options from site level to network level.
2693
+ $api_network_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true );
2694
+ $api_network_options->migrate_to_network();
2695
+
2696
+ // Migrate API cache to network level storage.
2697
+ FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME )->migrate_to_network();
2698
+
2699
+ self::$_accounts->set_option( 'ms_migration_complete', true, true );
2700
+ }
2701
+
2702
  #----------------------------------------------------------------------------------
2703
  #region Localization
2704
  #----------------------------------------------------------------------------------
2925
  }
2926
 
2927
  fs_redirect( $download_url );
2928
+ } else if ( fs_request_is_action( 'migrate_options_to_network' ) ) {
2929
+ check_admin_referer( 'migrate_options_to_network' );
2930
+
2931
+ self::migrate_options_to_network();
2932
  }
2933
  }
2934
 
6011
  * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
6012
  */
6013
  private function schedule_install_sync( $except_blog_id = 0 ) {
6014
+ $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
6015
  }
6016
 
6017
  /**
10598
  return;
10599
  }
10600
 
10601
+ if ( ! $this->is_premium() || $this->has_any_active_valid_license() ) {
10602
  // This is relevant only to the free versions and premium versions without an active license.
10603
  return;
10604
  }
15614
  return;
15615
  }
15616
 
15617
+ $site_clone = is_object( $site ) ? $site : $this->_site;
15618
+ $encrypted_site = clone $site_clone;
15619
 
15620
  $sites = self::get_all_sites( $this->_module_type, $network_level_or_blog_id );
15621
 
16313
  * @since 1.2.1
16314
  */
16315
  function has_active_valid_license() {
16316
+ return self::is_active_valid_license( $this->_license );
16317
+ }
16318
+
16319
+ /**
16320
+ * Check if a given license is active & valid (not expired).
16321
+ *
16322
+ * @author Vova Feldman (@svovaf)
16323
+ * @since 2.1.3
16324
+ *
16325
+ * @param FS_Plugin_License $license
16326
+ *
16327
+ * @return bool
16328
+ */
16329
+ private static function is_active_valid_license( $license ) {
16330
  return (
16331
+ is_object( $license ) &&
16332
+ FS_Plugin_License::is_valid_id( $license->id ) &&
16333
+ $license->is_active() &&
16334
+ $license->is_valid()
16335
  );
16336
  }
16337
 
16338
+ /**
16339
+ * Checks if there's any site that is associated with an active & valid license.
16340
+ * This logic is used to determine if the admin can download the premium code base from a network level admin.
16341
+ *
16342
+ * @author Vova Feldman (@svovaf)
16343
+ * @since 2.1.3
16344
+ *
16345
+ * @return bool
16346
+ */
16347
+ function has_any_active_valid_license() {
16348
+ if ( ! fs_is_network_admin() ) {
16349
+ return $this->has_active_valid_license();
16350
+ }
16351
+
16352
+ $installs = $this->get_blog_install_map();
16353
+ $all_plugin_licenses = self::get_all_licenses( $this->_module_id );
16354
+
16355
+ foreach ( $installs as $blog_id => $install ) {
16356
+ if ( ! FS_Plugin_License::is_valid_id( $install->license_id ) ) {
16357
+ continue;
16358
+ }
16359
+
16360
+ foreach ( $all_plugin_licenses as $license ) {
16361
+ if ( $license->id == $install->license_id ) {
16362
+ if ( self::is_active_valid_license( $license ) ) {
16363
+ return true;
16364
+ }
16365
+ }
16366
+ }
16367
+ }
16368
+
16369
+ return false;
16370
+ }
16371
+
16372
  /**
16373
  * Check if site assigned with license with enabled features.
16374
  *
17362
  * @return bool
17363
  */
17364
  private function _can_download_premium() {
17365
+ return $this->has_any_active_valid_license() ||
17366
  ( $this->is_trial() && ! $this->get_trial_plan()->is_free() );
17367
  }
17368
 
18515
  $this->_logger->entrance();
18516
 
18517
  $vars = array( 'id' => $this->_module_id );
18518
+
18519
+ /**
18520
+ * Added filter to the template to allow developers wrapping the template
18521
+ * in custom HTML (e.g. within a wizard/tabs).
18522
+ *
18523
+ * @author Vova Feldman (@svovaf)
18524
+ * @since 2.1.3
18525
+ */
18526
+ echo $this->apply_filters( 'templates/contact.php', fs_get_template( 'contact.php', $vars ) );
18527
  }
18528
 
18529
  #endregion ------------------------------------------------------------------------
18829
 
18830
  // Show promotion if never shown before and 24 hours after initial activation with FS.
18831
  if ( ! $was_promotion_shown_before &&
18832
+ $this->_storage->install_timestamp > ( time() - $this->apply_filters( 'show_first_trial_after_n_sec', WP_FS__TIME_24_HOURS_IN_SEC ) )
18833
  ) {
18834
  return false;
18835
  }
18836
 
18837
  // OR if promotion was shown before, try showing it every 30 days.
18838
  if ( $was_promotion_shown_before &&
18839
+ $this->apply_filters( 'reshow_trial_after_every_n_sec', 30 * WP_FS__TIME_24_HOURS_IN_SEC ) > time() - $last_time_trial_promotion_shown
18840
  ) {
18841
  return false;
18842
  }
freemius/includes/class-fs-plugin-updater.php CHANGED
@@ -82,7 +82,7 @@
82
 
83
  $this->add_transient_filters();
84
 
85
- if ( ! $this->_fs->has_active_valid_license() ) {
86
  /**
87
  * If user has the premium plugin's code but do NOT have an active license,
88
  * encourage him to upgrade by showing that there's a new release, but instead
@@ -114,7 +114,7 @@
114
  add_filter( 'upgrader_post_install', array( &$this, '_maybe_update_folder_name' ), 10, 3 );
115
  }
116
 
117
- if ( ! $this->_fs->has_active_valid_license() ) {
118
  add_filter( 'wp_prepare_themes_for_js', array( &$this, 'change_theme_update_info_html' ), 10, 1 );
119
  }
120
  }
82
 
83
  $this->add_transient_filters();
84
 
85
+ if ( ! $this->_fs->has_any_active_valid_license() ) {
86
  /**
87
  * If user has the premium plugin's code but do NOT have an active license,
88
  * encourage him to upgrade by showing that there's a new release, but instead
114
  add_filter( 'upgrader_post_install', array( &$this, '_maybe_update_folder_name' ), 10, 3 );
115
  }
116
 
117
+ if ( ! $this->_fs->has_any_active_valid_license() ) {
118
  add_filter( 'wp_prepare_themes_for_js', array( &$this, 'change_theme_update_info_html' ), 10, 1 );
119
  }
120
  }
freemius/includes/entities/class-fs-site.php CHANGED
@@ -150,6 +150,7 @@
150
  fs_starts_with( $subdomain, 'local.' ) ||
151
  fs_starts_with( $subdomain, 'dev.' ) ||
152
  fs_starts_with( $subdomain, 'test.' ) ||
 
153
  fs_starts_with( $subdomain, 'staging.' ) ||
154
 
155
  // Ends with.
@@ -171,7 +172,9 @@
171
  ( fs_ends_with($subdomain, 'pantheonsite.io') &&
172
  (fs_starts_with($subdomain, 'test-') || fs_starts_with($subdomain, 'dev-'))) ||
173
  // Cloudways
174
- fs_ends_with( $subdomain, '.cloudwaysapps.com' )
 
 
175
  );
176
  }
177
 
150
  fs_starts_with( $subdomain, 'local.' ) ||
151
  fs_starts_with( $subdomain, 'dev.' ) ||
152
  fs_starts_with( $subdomain, 'test.' ) ||
153
+ fs_starts_with( $subdomain, 'stage.' ) ||
154
  fs_starts_with( $subdomain, 'staging.' ) ||
155
 
156
  // Ends with.
172
  ( fs_ends_with($subdomain, 'pantheonsite.io') &&
173
  (fs_starts_with($subdomain, 'test-') || fs_starts_with($subdomain, 'dev-'))) ||
174
  // Cloudways
175
+ fs_ends_with( $subdomain, '.cloudwaysapps.com' ) ||
176
+ // Kinsta
177
+ (fs_ends_with($subdomain, '.kinsta.com') && fs_starts_with($subdomain, 'staging-'))
178
  );
179
  }
180
 
freemius/includes/fs-plugin-info-dialog.php CHANGED
@@ -203,7 +203,7 @@
203
 
204
  if ( is_object( $latest ) ) {
205
  $data->version = $latest->version;
206
- $data->last_updated = ! is_null( $latest->updated ) ? $latest->updated : $latest->created;
207
  $data->requires = $latest->requires_platform_version;
208
  $data->tested = $latest->tested_up_to_version;
209
  } else {
203
 
204
  if ( is_object( $latest ) ) {
205
  $data->version = $latest->version;
206
+ $data->last_updated = $latest->created;
207
  $data->requires = $latest->requires_platform_version;
208
  $data->tested = $latest->tested_up_to_version;
209
  } else {
freemius/start.php CHANGED
@@ -15,7 +15,7 @@
15
  *
16
  * @var string
17
  */
18
- $this_sdk_version = '2.1.2';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
15
  *
16
  * @var string
17
  */
18
+ $this_sdk_version = '2.1.3';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
freemius/templates/connect.php CHANGED
@@ -253,6 +253,17 @@
253
  <a class="show-license-resend-modal show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>"
254
  href="#"><?php fs_esc_html_echo_inline( "Can't find your license key?", 'cant-find-license-key', $slug ); ?></a>
255
  </div>
 
 
 
 
 
 
 
 
 
 
 
256
  <?php
257
  $send_updates_text = sprintf(
258
  '%s<span class="action-description"> - %s</span>',
253
  <a class="show-license-resend-modal show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>"
254
  href="#"><?php fs_esc_html_echo_inline( "Can't find your license key?", 'cant-find-license-key', $slug ); ?></a>
255
  </div>
256
+
257
+ <?php
258
+ /**
259
+ * Allows developers to include custom HTML after the license input container.
260
+ *
261
+ * @author Vova Feldman
262
+ * @since 2.1.2
263
+ */
264
+ $fs->do_action( 'connect/after_license_input' );
265
+ ?>
266
+
267
  <?php
268
  $send_updates_text = sprintf(
269
  '%s<span class="action-description"> - %s</span>',
freemius/templates/debug.php CHANGED
@@ -86,6 +86,16 @@
86
  <button class="button button-primary"><?php fs_esc_html_echo_inline( 'Sync Data From Server' ) ?></button>
87
  </form>
88
  </td>
 
 
 
 
 
 
 
 
 
 
89
  <td>
90
  <button id="fs_load_db_option" class="button"><?php fs_esc_html_echo_inline( 'Load DB Option' ) ?></button>
91
  </td>
86
  <button class="button button-primary"><?php fs_esc_html_echo_inline( 'Sync Data From Server' ) ?></button>
87
  </form>
88
  </td>
89
+ <?php if ( fs_is_network_admin() && true !== $fs_options->get_option( 'ms_migration_complete', false, true ) ) : ?>
90
+ <td>
91
+ <!-- Migrate Options to Network -->
92
+ <form action="" method="POST">
93
+ <input type="hidden" name="fs_action" value="migrate_options_to_network">
94
+ <?php wp_nonce_field( 'migrate_options_to_network' ) ?>
95
+ <button class="button button-primary"><?php fs_esc_html_echo_inline( 'Migrate Options to Network' ) ?></button>
96
+ </form>
97
+ </td>
98
+ <?php endif ?>
99
  <td>
100
  <button id="fs_load_db_option" class="button"><?php fs_esc_html_echo_inline( 'Load DB Option' ) ?></button>
101
  </td>
freemius/templates/forms/deactivation/form.php CHANGED
@@ -94,7 +94,7 @@ HTML;
94
  isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
95
  otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
96
  dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
97
- deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_active_valid_license() ? 'true' : 'false' ?>;
98
 
99
  $modal.appendTo($('body'));
100
 
94
  isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
95
  otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
96
  dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>,
97
+ deleteThemeUpdateData = <?php echo $fs->is_theme() && $fs->is_premium() && ! $fs->has_any_active_valid_license() ? 'true' : 'false' ?>;
98
 
99
  $modal.appendTo($('body'));
100
 
premmerce-url-manager.php CHANGED
@@ -3,15 +3,15 @@
3
  use Premmerce\UrlManager\UrlManagerPlugin;
4
 
5
  /**
6
- * WooCommerce Permalink Manager
7
  *
8
  * @package Premmerce\UrlManager
9
  *
10
  * @wordpress-plugin
11
- * Plugin Name: WooCommerce Permalink Manager
12
  * Plugin URI: https://premmerce.com/woocommerce-permalink-manager-remove-shop-product-product-category-url/
13
  * Description: Premmerce WooCommerce Permalink Manager allows you to change WooCommerce permalink and remove product and product_category slugs from the URL.
14
- * Version: 2.1.2
15
  * Author: premmerce
16
  * Author URI: https://premmerce.com/
17
  * License: GPL-2.0+
@@ -20,7 +20,7 @@ use Premmerce\UrlManager\UrlManagerPlugin;
20
  * Domain Path: /languages
21
  *
22
  * WC requires at least: 3.0.0
23
- * WC tested up to: 3.4
24
  */
25
 
26
  // If this file is called directly, abort.
3
  use Premmerce\UrlManager\UrlManagerPlugin;
4
 
5
  /**
6
+ * Premmerce WooCommerce Permalink Manager
7
  *
8
  * @package Premmerce\UrlManager
9
  *
10
  * @wordpress-plugin
11
+ * Plugin Name: Premmerce WooCommerce Permalink Manager
12
  * Plugin URI: https://premmerce.com/woocommerce-permalink-manager-remove-shop-product-product-category-url/
13
  * Description: Premmerce WooCommerce Permalink Manager allows you to change WooCommerce permalink and remove product and product_category slugs from the URL.
14
+ * Version: 2.1.3
15
  * Author: premmerce
16
  * Author URI: https://premmerce.com/
17
  * License: GPL-2.0+
20
  * Domain Path: /languages
21
  *
22
  * WC requires at least: 3.0.0
23
+ * WC tested up to: 3.5
24
  */
25
 
26
  // If this file is called directly, abort.
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
- === WooCommerce Permalink Manager ===
2
- Contributors: premmerce, freemius
3
  Tags: woocommerce url, remove product, remove product_category, woocommerce permalink, woocommerce, woocommerce seo
4
  Requires at least: 4.8
5
  Tested up to: 4.9.6
6
- Stable tag: 2.1.2
7
  Requires PHP: 5.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -12,7 +12,7 @@ Premmerce WooCommerce Permalink Manager allows you to change WooCommerce permali
12
 
13
  == Description ==
14
 
15
- WooCommerce Permalink Manager is developed to improve the current WooCommerce URL configuration features and provide your store with better display options and additional SEO capabilities to adhere to [WooCommerce SEO Audit](https://premmerce.com/complete-woocommerce-seo-guide-tips/) standards.
16
 
17
  [youtube https://www.youtube.com/watch?v=-TMpzsSPiMU]
18
 
@@ -33,9 +33,9 @@ WooCommerce Permalink Manager is developed to improve the current WooCommerce UR
33
  * The ability to choose a main category to generate a product URL.
34
  * Automatic adding of the ‘rel=canonical’ attribute to duplicate pages to improve SEO.
35
 
36
- = Additional features available in WooCommerce Permalink Manager Premium only: =
37
 
38
- [WooCommerce Permalink Manager Premium](https://premmerce.com/woocommerce-permalink-manager/)
39
 
40
  * The ability to remove the base from the product tags URL.
41
  * Automatic adding of 301 redirects to duplicated pages to improve SEO and site navigation.
@@ -69,10 +69,10 @@ We have tested how the plugin works with the basic WooCommerce kit and the stand
69
  The plugin works perfectly with the Yoast SEO plugin installed. No link duplicates are generated. All similar URLs are automatically tagged as canonical in accordance with the search engines’ recommendations.
70
 
71
  = Documentation =
72
- Full documentation is available here: [WooCommerce permalink manager](https://premmerce.com/woocommerce-permalink-manager-remove-shop-product-product-category-url/)
73
 
74
  = Installation Instructions =
75
- Go to Plugins -> Add New section from your admin account and search for WooCommerce Permalink Manager.
76
 
77
  You can also install this plugin manually:
78
  * Download the plugin’s ZIP archive and unzip it.
@@ -185,5 +185,9 @@ Release Date: Aug 2, 2018
185
 
186
  * Fixed upgrade page
187
 
 
188
 
 
189
 
 
 
1
+ === Premmerce WooCommerce Permalink Manager ===
2
+ Contributors: premmerce
3
  Tags: woocommerce url, remove product, remove product_category, woocommerce permalink, woocommerce, woocommerce seo
4
  Requires at least: 4.8
5
  Tested up to: 4.9.6
6
+ Stable tag: 2.1.3
7
  Requires PHP: 5.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
13
  == Description ==
14
 
15
+ Premmerce WooCommerce Permalink Manager is developed to improve the current WooCommerce URL configuration features and provide your store with better display options and additional SEO capabilities to adhere to [WooCommerce SEO Audit](https://premmerce.com/complete-woocommerce-seo-guide-tips/) standards.
16
 
17
  [youtube https://www.youtube.com/watch?v=-TMpzsSPiMU]
18
 
33
  * The ability to choose a main category to generate a product URL.
34
  * Automatic adding of the ‘rel=canonical’ attribute to duplicate pages to improve SEO.
35
 
36
+ = Additional features available in Premmerce WooCommerce Permalink Manager Premium only: =
37
 
38
+ [Premmerce WooCommerce Permalink Manager Premium](https://premmerce.com/woocommerce-permalink-manager/)
39
 
40
  * The ability to remove the base from the product tags URL.
41
  * Automatic adding of 301 redirects to duplicated pages to improve SEO and site navigation.
69
  The plugin works perfectly with the Yoast SEO plugin installed. No link duplicates are generated. All similar URLs are automatically tagged as canonical in accordance with the search engines’ recommendations.
70
 
71
  = Documentation =
72
+ Full documentation is available here: [Premmerce WooCommerce Permalink Manager](https://premmerce.com/woocommerce-permalink-manager-remove-shop-product-product-category-url/)
73
 
74
  = Installation Instructions =
75
+ Go to Plugins -> Add New section from your admin account and search for Premmerce WooCommerce Permalink Manager.
76
 
77
  You can also install this plugin manually:
78
  * Download the plugin’s ZIP archive and unzip it.
185
 
186
  * Fixed upgrade page
187
 
188
+ = 2.1.3 =
189
 
190
+ Release Date: Nov 14, 2018
191
 
192
+ * Updated freemius version to 2.1.3
193
+ * Added WooCommerce 3.5 support