FooGallery – Image Gallery WordPress Plugin - Version 1.10.3

Version Description

  • Date Updated : 2021-20-02
  • Fix : fixed a fatal error on some installs (only update if you have issues with 1.10.1!)
Download this release

Release Info

Developer bradvin
Plugin Icon 128x128 FooGallery – Image Gallery WordPress Plugin
Version 1.10.3
Comparing to
See all releases

Code changes from version 1.9.53 to 1.10.3

Files changed (64) hide show
  1. README.txt +16 -1
  2. foogallery.php +5 -4
  3. freemius/LICENSE.txt +1 -1
  4. freemius/assets/css/admin/account.css +1 -1
  5. freemius/assets/css/admin/common.css +2 -2
  6. freemius/assets/css/admin/connect.css +1 -1
  7. freemius/includes/class-freemius.php +79 -41
  8. freemius/includes/class-fs-logger.php +691 -691
  9. freemius/includes/entities/class-fs-site.php +252 -235
  10. freemius/includes/entities/class-fs-user.php +61 -78
  11. freemius/languages/freemius-cs_CZ.mo +0 -0
  12. freemius/languages/freemius-da_DK.mo +0 -0
  13. freemius/languages/freemius-en.mo +0 -0
  14. freemius/languages/freemius-es_ES.mo +0 -0
  15. freemius/languages/freemius-fr_FR.mo +0 -0
  16. freemius/languages/freemius-he_IL.mo +0 -0
  17. freemius/languages/freemius-hu_HU.mo +0 -0
  18. freemius/languages/freemius-it_IT.mo +0 -0
  19. freemius/languages/freemius-ja.mo +0 -0
  20. freemius/languages/freemius-nl_NL.mo +0 -0
  21. freemius/languages/freemius-ru_RU.mo +0 -0
  22. freemius/languages/freemius-ta.mo +0 -0
  23. freemius/languages/freemius-zh_CN.mo +0 -0
  24. freemius/languages/freemius.pot +345 -313
  25. freemius/start.php +3 -3
  26. freemius/templates/account.php +5 -3
  27. freemius/templates/connect.php +49 -37
  28. freemius/templates/forms/affiliation.php +508 -508
  29. freemius/templates/forms/license-activation.php +3 -1
  30. gutenberg/src/block/index.js +1 -1
  31. includes/WPThumb/wpthumb.background-fill.php +0 -146
  32. includes/WPThumb/wpthumb.crop-from-position.php +0 -85
  33. includes/WPThumb/wpthumb.image-editor.php +0 -46
  34. includes/WPThumb/wpthumb.php +0 -836
  35. includes/WPThumb/wpthumb.shortcodes.php +0 -49
  36. includes/WPThumb/wpthumb.watermark.php +0 -392
  37. includes/admin/class-admin.php +0 -1
  38. includes/admin/class-gallery-metabox-items.php +1 -1
  39. includes/admin/class-gallery-metaboxes.php +20 -12
  40. includes/admin/class-settings-image-optimization.php +0 -32
  41. includes/admin/class-settings.php +93 -55
  42. includes/class-foogallery-crop-position.php +227 -0
  43. includes/class-foogallery-default-crop-position.php +0 -80
  44. includes/class-thumbnails.php +48 -37
  45. includes/class-wpthumb-enhancements.php +0 -70
  46. includes/functions.php +83 -1
  47. includes/includes.php +4 -9
  48. includes/thumbs/class-foogallery-thumb-engine.php +62 -0
  49. includes/thumbs/class-foogallery-thumb-manager.php +21 -0
  50. includes/thumbs/default/class-foogallery-thumb-engine-default.php +198 -0
  51. includes/thumbs/default/class-foogallery-thumb-generator-background-fill.php +162 -0
  52. includes/thumbs/default/class-foogallery-thumb-generator.php +491 -0
  53. includes/thumbs/default/class-foogallery-thumb-image-editor-gd.php +50 -0
  54. includes/thumbs/default/class-foogallery-thumb-image-editor-imagick.php +45 -0
  55. includes/thumbs/default/tests/test1.png +0 -0
  56. includes/thumbs/default/tests/test2.png +0 -0
  57. includes/thumbs/default/tests/test3 +0 -0
  58. includes/thumbs/default/tests/test4.gif +0 -0
  59. includes/thumbs/default/tests/test5.jpg +0 -0
  60. includes/thumbs/default/tests/test6.bmp +0 -0
  61. includes/thumbs/dummy/class-foogallery-thumb-engine-dummy.php +78 -0
  62. includes/thumbs/includes.php +15 -0
  63. includes/thumbs/shortpixel/class-foogallery-thumb-engine-shortpixel.php +11 -0
  64. js/foogallery.admin.min.js +8 -8
README.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: bradvin, steveush, fooplugins
3
  Donate link: https://fooplugins.com
4
  Tags: gallery, image gallery, photo gallery, responsive gallery, wordpress gallery plugin, best gallery plugin, albums, media gallery, video gallery, lightbox
5
  Requires at least: 3.9
6
- Tested up to: 5.6
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -227,6 +227,21 @@ Please update in order to for FooGallery to work in WP 5.5+!
227
 
228
  == Changelog ==
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  = 1.9.53 =
231
  * Date Updated : 2021-23-01
232
  * Update : FooGallery client side 1.4.26
3
  Donate link: https://fooplugins.com
4
  Tags: gallery, image gallery, photo gallery, responsive gallery, wordpress gallery plugin, best gallery plugin, albums, media gallery, video gallery, lightbox
5
  Requires at least: 3.9
6
+ Tested up to: 5.7
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
227
 
228
  == Changelog ==
229
 
230
+ = 1.10.3 =
231
+ * Date Updated : 2021-20-02
232
+ * Fix : fixed a fatal error on some installs (only update if you have issues with 1.10.1!)
233
+
234
+ = 1.10.1 =
235
+ * Date Updated : 2021-18-02
236
+ * Fix : fixed a fatal error with PHP 5.6
237
+
238
+ = 1.10.0 =
239
+ * Date Updated : 2021-18-02
240
+ * Update : Removed WPThumb library completely
241
+ * Update : Updated to Freemius SDK 2.4.2
242
+ * Fix : updated FooGallery block category to 'media'
243
+
244
+
245
  = 1.9.53 =
246
  * Date Updated : 2021-23-01
247
  * Update : FooGallery client side 1.4.26
foogallery.php CHANGED
@@ -3,7 +3,7 @@
3
  /*
4
  Plugin Name: FooGallery
5
  Description: FooGallery is the most intuitive and extensible gallery management tool ever created for WordPress
6
- Version: 1.9.53
7
  Author: FooPlugins
8
  Plugin URI: http://fooplugins.com/foogallery/
9
  Author URI: http://fooplugins.com
@@ -25,7 +25,7 @@ if ( function_exists( 'foogallery_fs' ) ) {
25
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
27
  define( 'FOOGALLERY_FILE', __FILE__ );
28
- define( 'FOOGALLERY_VERSION', '1.9.53' );
29
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
30
  require_once FOOGALLERY_PATH . 'includes/constants.php';
31
  // Create a helper function for easy SDK access.
@@ -135,11 +135,12 @@ if ( function_exists( 'foogallery_fs' ) ) {
135
  new FooGallery_Public();
136
  }
137
 
 
 
138
  new FooGallery_Shortcodes();
139
  new FooGallery_Thumbnails();
140
  new FooGallery_Attachment_Filters();
141
  new FooGallery_Retina();
142
- new FooGallery_WPThumb_Enhancements();
143
  new FooGallery_Animated_Gif_Support();
144
  new FooGallery_Cache();
145
  new FooGallery_Common_Fields();
@@ -150,7 +151,7 @@ if ( function_exists( 'foogallery_fs' ) ) {
150
  new FooGallery_Upgrade();
151
  new FooGallery_Compatibility();
152
  new FooGallery_Extensions_Compatibility();
153
- new FooGallery_Default_Crop_Position();
154
  new FooGallery_ForceHttps();
155
  $checker = new FooGallery_Version_Check();
156
  $checker->wire_up_checker();
3
  /*
4
  Plugin Name: FooGallery
5
  Description: FooGallery is the most intuitive and extensible gallery management tool ever created for WordPress
6
+ Version: 1.10.3
7
  Author: FooPlugins
8
  Plugin URI: http://fooplugins.com/foogallery/
9
  Author URI: http://fooplugins.com
25
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
27
  define( 'FOOGALLERY_FILE', __FILE__ );
28
+ define( 'FOOGALLERY_VERSION', '1.10.3' );
29
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
30
  require_once FOOGALLERY_PATH . 'includes/constants.php';
31
  // Create a helper function for easy SDK access.
135
  new FooGallery_Public();
136
  }
137
 
138
+ //initialize the thumbnail manager
139
+ new FooGallery_Thumb_Manager();
140
  new FooGallery_Shortcodes();
141
  new FooGallery_Thumbnails();
142
  new FooGallery_Attachment_Filters();
143
  new FooGallery_Retina();
 
144
  new FooGallery_Animated_Gif_Support();
145
  new FooGallery_Cache();
146
  new FooGallery_Common_Fields();
151
  new FooGallery_Upgrade();
152
  new FooGallery_Compatibility();
153
  new FooGallery_Extensions_Compatibility();
154
+ new FooGallery_Crop_Position();
155
  new FooGallery_ForceHttps();
156
  $checker = new FooGallery_Version_Check();
157
  $checker->wire_up_checker();
freemius/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
  GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
  Everyone is permitted to copy and distribute verbatim copies
6
  of this license document, but changing it is not allowed.
7
 
1
  GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
  Everyone is permitted to copy and distribute verbatim copies
6
  of this license document, but changing it is not allowed.
7
 
freemius/assets/css/admin/account.css CHANGED
@@ -1 +1 @@
1
- label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id="license_not_whitelabeled"].success,.fs-notice[data-id="license_whitelabeled"].success{color:inherit;border-left-color:#00a0d2}.fs-notice[data-id="license_not_whitelabeled"].success label.fs-plugin-title,.fs-notice[data-id="license_whitelabeled"].success label.fs-plugin-title{display:none}#fs_account .postbox,#fs_account .widefat{max-width:800px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account h3 .dashicons{width:26px;height:26px;font-size:1.3em}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}#fs_account_details .button-group{float:right}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table code{line-height:28px}.fs-key-value-table var,.fs-key-value-table code,.fs-key-value-table input[type="text"]{color:#0073AA;font-size:16px;background:none}.fs-key-value-table input[type="text"]{width:100%;font-weight:bold}.fs-field-beta_program label{margin-left:7px}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_sites .fs-scrollable-table .fs-table-body{max-height:200px;overflow:auto;border:1px solid #e5e5e5}#fs_sites .fs-scrollable-table .fs-table-body>table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:grey;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}
1
+ label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id="license_not_whitelabeled"].success,.fs-notice[data-id="license_whitelabeled"].success{color:inherit;border-left-color:#00a0d2}.fs-notice[data-id="license_not_whitelabeled"].success label.fs-plugin-title,.fs-notice[data-id="license_whitelabeled"].success label.fs-plugin-title{display:none}#fs_account .postbox,#fs_account .widefat{max-width:800px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account h3 .dashicons{width:26px;height:26px;font-size:1.3em}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}#fs_account_details .button-group{float:right}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table code{line-height:28px}.fs-key-value-table var,.fs-key-value-table code,.fs-key-value-table input[type="text"]{color:#0073AA;font-size:16px;background:none}.fs-key-value-table input[type="text"]{width:100%;font-weight:bold}.fs-field-beta_program label{margin-left:7px}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_sites .fs-scrollable-table .fs-table-body{max-height:200px;overflow:auto;border:1px solid #e5e5e5}#fs_sites .fs-scrollable-table .fs-table-body>table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:grey;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}
freemius/assets/css/admin/common.css CHANGED
@@ -1,2 +1,2 @@
1
- .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
- .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 500px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
1
+ .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
+ .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 1250px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
freemius/assets/css/admin/connect.css CHANGED
@@ -1 +1 @@
1
- #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions .fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:0;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li .fs-switch{float:left}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,0.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:white;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:52px;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms{background:rgba(140,140,140,0.64)}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}
1
+ #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions>.fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li>i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff !important;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:-17px;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left;text-transform:none !important}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right;left:auto;right:-17px}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li .fs-switch{float:left}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,0.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:white;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:52px;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms{background:rgba(140,140,140,0.64)}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}#license_issues_link{display:block;text-align:center;font-size:0.9em;margin-top:10px}
freemius/includes/class-freemius.php CHANGED
@@ -384,6 +384,13 @@
384
  * @var boolean|null
385
  */
386
  private $_use_external_pricing = null;
 
 
 
 
 
 
 
387
 
388
  #endregion
389
 
@@ -5484,7 +5491,7 @@
5484
  function is_extensions_tracking_allowed() {
5485
  return ( true === $this->apply_filters(
5486
  'is_extensions_tracking_allowed',
5487
- $this->_storage->get( 'is_extensions_tracking_allowed', true )
5488
  ) );
5489
  }
5490
 
@@ -5528,10 +5535,12 @@
5528
  * @author Leo Fajardo (@leorw)
5529
  * @since 2.3.2
5530
  *
5531
- * @param bool $is_enabled
5532
  */
5533
- private function update_extensions_tracking_flag( $is_enabled ) {
5534
- $this->_storage->store( 'is_extensions_tracking_allowed', $is_enabled );
 
 
5535
  }
5536
 
5537
  /**
@@ -6860,8 +6869,6 @@
6860
  */
6861
  function _sync_cron_method( array $blog_ids, $current_blog_id = null ) {
6862
  if ( $this->is_registered() ) {
6863
- $this->sync_user_beta_mode();
6864
-
6865
  if ( $this->has_paid_plan() ) {
6866
  // Initiate background plan sync.
6867
  $this->_sync_license( true, false, $current_blog_id );
@@ -7234,7 +7241,8 @@
7234
  }
7235
 
7236
  if ( $this->is_plugin_new_install() || $this->is_only_premium() ) {
7237
- if ( ! $this->_anonymous_mode ) {
 
7238
  // Show notice for new plugin installations.
7239
  $this->_admin_notices->add(
7240
  sprintf(
@@ -7285,6 +7293,10 @@
7285
  * @return bool
7286
  */
7287
  private function should_add_sticky_optin_notice() {
 
 
 
 
7288
  if ( fs_is_network_admin() ) {
7289
  if ( ! $this->_is_network_active ) {
7290
  return false;
@@ -13238,26 +13250,25 @@
13238
  self::shoot_ajax_failure();
13239
  }
13240
 
13241
- $user = $this->get_api_user_scope()->call(
13242
  '',
13243
  'put',
13244
  array(
13245
- 'plugin_id' => $this->get_id(),
13246
  'is_beta' => ( 'true' == $is_beta ),
13247
  'fields' => 'is_beta'
13248
  )
13249
  );
13250
 
13251
- if ( ! $this->is_api_result_entity( $user ) ) {
13252
  self::shoot_ajax_failure(
13253
- FS_Api::is_api_error_object( $user ) ?
13254
- $user->error->message :
13255
  fs_text_inline( "An unknown error has occurred while trying to set the user's beta mode.", 'unknown-error-occurred', $this->get_slug() )
13256
  );
13257
  }
13258
 
13259
- $this->_user->is_beta = $user->is_beta;
13260
- $this->_store_user();
13261
 
13262
  self::shoot_ajax_response( array( 'success' => true ) );
13263
  }
@@ -13292,7 +13303,7 @@
13292
  fs_request_get( 'blog_id', null ),
13293
  fs_request_get( 'module_id', null, 'post' ),
13294
  fs_request_get( 'user_id', null ),
13295
- fs_request_get_bool( 'is_extensions_tracking_allowed', true )
13296
  );
13297
 
13298
  if (
@@ -13482,7 +13493,31 @@
13482
  * @return string
13483
  */
13484
  function get_pricing_js_path() {
13485
- return $this->apply_filters( 'freemius_pricing_js_path', WP_FS__DIR_INCLUDES . '/freemius-pricing/freemius-pricing.js' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13486
  }
13487
 
13488
  /**
@@ -13527,7 +13562,7 @@
13527
  $blog_id = null,
13528
  $plugin_id = null,
13529
  $license_owner_id = null,
13530
- $is_extensions_tracking_allowed = true
13531
  ) {
13532
  $this->_logger->entrance();
13533
 
@@ -16448,19 +16483,6 @@
16448
  );
16449
  }
16450
 
16451
- /**
16452
- * @author Leo Fajardo (@leorw)
16453
- * @since 2.3.0
16454
- */
16455
- private function sync_user_beta_mode() {
16456
- $user = $this->get_api_user_scope()->get( '/?plugin_id=' . $this->get_id() . '&fields=is_beta' );
16457
-
16458
- if ( $this->is_api_result_entity( $user ) ) {
16459
- $this->_user->is_beta = $user->is_beta;
16460
- $this->_store_user();
16461
- }
16462
- }
16463
-
16464
  /**
16465
  * @author Vova Feldman (@svovaf)
16466
  * @since 1.1.7.4
@@ -17148,9 +17170,7 @@
17148
  $this->disable_opt_in_notice_and_lock_user();
17149
  }
17150
 
17151
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17152
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17153
- }
17154
 
17155
  return $this->setup_account(
17156
  $this->_user,
@@ -17195,9 +17215,7 @@
17195
  $this->disable_opt_in_notice_and_lock_user();
17196
  }
17197
 
17198
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17199
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17200
- }
17201
 
17202
  $sites = array();
17203
  foreach ( $site_ids as $site_id ) {
@@ -17240,9 +17258,7 @@
17240
  $this->disable_opt_in_notice_and_lock_user();
17241
  }
17242
 
17243
- if ( ! is_null( $is_extensions_tracking_allowed ) ) {
17244
- $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
17245
- }
17246
 
17247
  $install_ids = array();
17248
 
@@ -17353,7 +17369,7 @@
17353
  */
17354
  $license_key = fs_request_get( 'license_secret_key' );
17355
 
17356
- $this->update_extensions_tracking_flag( fs_request_get_bool( 'is_extensions_tracking_allowed', true ) );
17357
 
17358
  $this->install_with_current_user( $license_key );
17359
  }
@@ -20605,6 +20621,20 @@
20605
  }
20606
  }
20607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20608
  if ( $this->is_addon() || $this->has_addons() ) {
20609
  /**
20610
  * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded,
@@ -21298,7 +21328,7 @@
21298
 
21299
  if ( $this->has_secret_key() ) {
21300
  $endpoint = add_query_arg( 'type', 'all', $endpoint );
21301
- } else if ( $this->is_registered() && $this->_user->is_beta() ) {
21302
  $endpoint = add_query_arg( 'type', 'beta', $endpoint );
21303
  }
21304
 
@@ -23396,6 +23426,14 @@
23396
  return;
23397
  }
23398
 
 
 
 
 
 
 
 
 
23399
  if ( fs_is_network_admin() ) {
23400
  if ( ! $this->_is_network_active ) {
23401
  // Don't add tracking links when browsing the network WP Admin and the plugin is not network active.
384
  * @var boolean|null
385
  */
386
  private $_use_external_pricing = null;
387
+ /**
388
+ * @author Leo Fajardo (@leorw)
389
+ * @since 2.4.2
390
+ *
391
+ * @var string|null
392
+ */
393
+ private $_pricing_js_path = null;
394
 
395
  #endregion
396
 
5491
  function is_extensions_tracking_allowed() {
5492
  return ( true === $this->apply_filters(
5493
  'is_extensions_tracking_allowed',
5494
+ $this->_storage->get( 'is_extensions_tracking_allowed', null )
5495
  ) );
5496
  }
5497
 
5535
  * @author Leo Fajardo (@leorw)
5536
  * @since 2.3.2
5537
  *
5538
+ * @param bool|null $is_enabled
5539
  */
5540
+ function update_extensions_tracking_flag( $is_enabled ) {
5541
+ if ( is_bool( $is_enabled ) ) {
5542
+ $this->_storage->store( 'is_extensions_tracking_allowed', $is_enabled );
5543
+ }
5544
  }
5545
 
5546
  /**
6869
  */
6870
  function _sync_cron_method( array $blog_ids, $current_blog_id = null ) {
6871
  if ( $this->is_registered() ) {
 
 
6872
  if ( $this->has_paid_plan() ) {
6873
  // Initiate background plan sync.
6874
  $this->_sync_license( true, false, $current_blog_id );
7241
  }
7242
 
7243
  if ( $this->is_plugin_new_install() || $this->is_only_premium() ) {
7244
+ if ( ! $this->_anonymous_mode &&
7245
+ ( ! $this->is_addon() || ! $this->_parent->is_anonymous() ) ) {
7246
  // Show notice for new plugin installations.
7247
  $this->_admin_notices->add(
7248
  sprintf(
7293
  * @return bool
7294
  */
7295
  private function should_add_sticky_optin_notice() {
7296
+ if ( $this->is_addon() && $this->_parent->is_anonymous() ) {
7297
+ return false;
7298
+ }
7299
+
7300
  if ( fs_is_network_admin() ) {
7301
  if ( ! $this->_is_network_active ) {
7302
  return false;
13250
  self::shoot_ajax_failure();
13251
  }
13252
 
13253
+ $site = $this->get_api_site_scope()->call(
13254
  '',
13255
  'put',
13256
  array(
 
13257
  'is_beta' => ( 'true' == $is_beta ),
13258
  'fields' => 'is_beta'
13259
  )
13260
  );
13261
 
13262
+ if ( ! $this->is_api_result_entity( $site ) ) {
13263
  self::shoot_ajax_failure(
13264
+ FS_Api::is_api_error_object( $site ) ?
13265
+ $site->error->message :
13266
  fs_text_inline( "An unknown error has occurred while trying to set the user's beta mode.", 'unknown-error-occurred', $this->get_slug() )
13267
  );
13268
  }
13269
 
13270
+ $this->_site->is_beta = $site->is_beta;
13271
+ $this->_store_site();
13272
 
13273
  self::shoot_ajax_response( array( 'success' => true ) );
13274
  }
13303
  fs_request_get( 'blog_id', null ),
13304
  fs_request_get( 'module_id', null, 'post' ),
13305
  fs_request_get( 'user_id', null ),
13306
+ fs_request_get_bool( 'is_extensions_tracking_allowed', null )
13307
  );
13308
 
13309
  if (
13493
  * @return string
13494
  */
13495
  function get_pricing_js_path() {
13496
+ if ( ! isset( $this->_pricing_js_path ) ) {
13497
+ $pricing_js_path = $this->apply_filters( 'freemius_pricing_js_path', '' );
13498
+
13499
+ if ( empty( $pricing_js_path ) ) {
13500
+ global $fs_active_plugins;
13501
+
13502
+ foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) {
13503
+ if ( $data->plugin_path == $this->get_plugin_basename() ) {
13504
+ $plugin_or_theme_root_dir = ( $this->is_plugin() ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) );
13505
+
13506
+ $pricing_js_path = $plugin_or_theme_root_dir
13507
+ . '/'
13508
+ // The basename will be `plugins`, `themes`, or the basename of a custom plugins or themes directory.
13509
+ . str_replace( '../' . basename( $plugin_or_theme_root_dir ) . '/', '', $sdk_path )
13510
+ . '/includes/freemius-pricing/freemius-pricing.js';
13511
+
13512
+ break;
13513
+ }
13514
+ }
13515
+ }
13516
+
13517
+ $this->_pricing_js_path = $pricing_js_path;
13518
+ }
13519
+
13520
+ return $this->_pricing_js_path;
13521
  }
13522
 
13523
  /**
13562
  $blog_id = null,
13563
  $plugin_id = null,
13564
  $license_owner_id = null,
13565
+ $is_extensions_tracking_allowed = null
13566
  ) {
13567
  $this->_logger->entrance();
13568
 
16483
  );
16484
  }
16485
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16486
  /**
16487
  * @author Vova Feldman (@svovaf)
16488
  * @since 1.1.7.4
17170
  $this->disable_opt_in_notice_and_lock_user();
17171
  }
17172
 
17173
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17174
 
17175
  return $this->setup_account(
17176
  $this->_user,
17215
  $this->disable_opt_in_notice_and_lock_user();
17216
  }
17217
 
17218
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17219
 
17220
  $sites = array();
17221
  foreach ( $site_ids as $site_id ) {
17258
  $this->disable_opt_in_notice_and_lock_user();
17259
  }
17260
 
17261
+ $this->update_extensions_tracking_flag( $is_extensions_tracking_allowed );
 
 
17262
 
17263
  $install_ids = array();
17264
 
17369
  */
17370
  $license_key = fs_request_get( 'license_secret_key' );
17371
 
17372
+ $this->update_extensions_tracking_flag( fs_request_get_bool( 'is_extensions_tracking_allowed', null ) );
17373
 
17374
  $this->install_with_current_user( $license_key );
17375
  }
20621
  }
20622
  }
20623
 
20624
+ if ( ! $this->is_addon() &&
20625
+ $this->_site->is_beta() !== $site->is_beta
20626
+ ) {
20627
+ // Beta flag updated.
20628
+ $this->_site = $site;
20629
+
20630
+ $this->_store_site(
20631
+ true,
20632
+ $is_site_level_sync ?
20633
+ null :
20634
+ $this->get_network_install_blog_id()
20635
+ );
20636
+ }
20637
+
20638
  if ( $this->is_addon() || $this->has_addons() ) {
20639
  /**
20640
  * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded,
21328
 
21329
  if ( $this->has_secret_key() ) {
21330
  $endpoint = add_query_arg( 'type', 'all', $endpoint );
21331
+ } else if ( is_object( $this->_site ) && $this->_site->is_beta() ) {
21332
  $endpoint = add_query_arg( 'type', 'beta', $endpoint );
21333
  }
21334
 
23426
  return;
23427
  }
23428
 
23429
+ if (
23430
+ $this->is_addon() &&
23431
+ ! $this->is_only_premium() &&
23432
+ $this->_parent->is_anonymous()
23433
+ ) {
23434
+ return;
23435
+ }
23436
+
23437
  if ( fs_is_network_admin() ) {
23438
  if ( ! $this->_is_network_active ) {
23439
  // Don't add tracking links when browsing the network WP Admin and the plugin is not network active.
freemius/includes/class-fs-logger.php CHANGED
@@ -1,691 +1,691 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2015, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.0.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Logger {
14
- private $_id;
15
- private $_on = false;
16
- private $_echo = false;
17
- private $_file_start = 0;
18
- /**
19
- * @var int PHP Process ID.
20
- */
21
- private static $_processID;
22
- /**
23
- * @var string PHP Script user name.
24
- */
25
- private static $_ownerName;
26
- /**
27
- * @var bool Is storage logging turned on.
28
- */
29
- private static $_isStorageLoggingOn;
30
- /**
31
- * @var int ABSPATH length.
32
- */
33
- private static $_abspathLength;
34
-
35
- private static $LOGGERS = array();
36
- private static $LOG = array();
37
- private static $CNT = 0;
38
- private static $_HOOKED_FOOTER = false;
39
-
40
- private function __construct( $id, $on = false, $echo = false ) {
41
- $this->_id = $id;
42
-
43
- $bt = debug_backtrace();
44
- $caller = $bt[2];
45
-
46
- if ( false !== strpos( $caller['file'], 'plugins' ) ) {
47
- $this->_file_start = strpos( $caller['file'], 'plugins' ) + strlen( 'plugins/' );
48
- } else {
49
- $this->_file_start = strpos( $caller['file'], 'themes' ) + strlen( 'themes/' );
50
- }
51
-
52
- if ( $on ) {
53
- $this->on();
54
- }
55
- if ( $echo ) {
56
- $this->echo_on();
57
- }
58
- }
59
-
60
- /**
61
- * @param string $id
62
- * @param bool $on
63
- * @param bool $echo
64
- *
65
- * @return FS_Logger
66
- */
67
- public static function get_logger( $id, $on = false, $echo = false ) {
68
- $id = strtolower( $id );
69
-
70
- if ( ! isset( self::$_processID ) ) {
71
- self::init();
72
- }
73
-
74
- if ( ! isset( self::$LOGGERS[ $id ] ) ) {
75
- self::$LOGGERS[ $id ] = new FS_Logger( $id, $on, $echo );
76
- }
77
-
78
- return self::$LOGGERS[ $id ];
79
- }
80
-
81
- /**
82
- * Initialize logging global info.
83
- *
84
- * @author Vova Feldman (@svovaf)
85
- * @since 1.2.1.6
86
- */
87
- private static function init() {
88
- self::$_ownerName = function_exists( 'get_current_user' ) ?
89
- get_current_user() :
90
- 'unknown';
91
- self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
92
- self::$_abspathLength = strlen( ABSPATH );
93
- self::$_processID = mt_rand( 0, 32000 );
94
-
95
- // Process ID may be `false` on errors.
96
- if ( ! is_numeric( self::$_processID ) ) {
97
- self::$_processID = 0;
98
- }
99
- }
100
-
101
- private static function hook_footer() {
102
- if ( self::$_HOOKED_FOOTER ) {
103
- return;
104
- }
105
-
106
- if ( is_admin() ) {
107
- add_action( 'admin_footer', 'FS_Logger::dump', 100 );
108
- } else {
109
- add_action( 'wp_footer', 'FS_Logger::dump', 100 );
110
- }
111
- }
112
-
113
- function is_on() {
114
- return $this->_on;
115
- }
116
-
117
- function on() {
118
- $this->_on = true;
119
-
120
- if ( ! function_exists( 'dbDelta' ) ) {
121
- require_once ABSPATH . 'wp-admin/includes/upgrade.php';
122
- }
123
-
124
- self::hook_footer();
125
- }
126
-
127
- function echo_on() {
128
- $this->on();
129
-
130
- $this->_echo = true;
131
- }
132
-
133
- function is_echo_on() {
134
- return $this->_echo;
135
- }
136
-
137
- function get_id() {
138
- return $this->_id;
139
- }
140
-
141
- function get_file() {
142
- return $this->_file_start;
143
- }
144
-
145
- private function _log( &$message, $type = 'log', $wrapper ) {
146
- if ( ! $this->is_on() ) {
147
- return;
148
- }
149
-
150
- $bt = debug_backtrace();
151
- $depth = $wrapper ? 3 : 2;
152
- while ( $depth < count( $bt ) - 1 && 'eval' === $bt[ $depth ]['function'] ) {
153
- $depth ++;
154
- }
155
-
156
- $caller = $bt[ $depth ];
157
-
158
- /**
159
- * Retrieve the correct call file & line number from backtrace
160
- * when logging from a wrapper method.
161
- *
162
- * @author Vova Feldman
163
- * @since 1.2.1.6
164
- */
165
- if ( empty( $caller['line'] ) ) {
166
- $depth --;
167
-
168
- while ( $depth >= 0 ) {
169
- if ( ! empty( $bt[ $depth ]['line'] ) ) {
170
- $caller['line'] = $bt[ $depth ]['line'];
171
- $caller['file'] = $bt[ $depth ]['file'];
172
- break;
173
- }
174
- }
175
- }
176
-
177
- $log = array_merge( $caller, array(
178
- 'cnt' => self::$CNT ++,
179
- 'logger' => $this,
180
- 'timestamp' => microtime( true ),
181
- 'log_type' => $type,
182
- 'msg' => $message,
183
- ) );
184
-
185
- if ( self::$_isStorageLoggingOn ) {
186
- $this->db_log( $type, $message, self::$CNT, $caller );
187
- }
188
-
189
- self::$LOG[] = $log;
190
-
191
- if ( $this->is_echo_on() && ! Freemius::is_ajax() ) {
192
- echo self::format_html( $log ) . "\n";
193
- }
194
- }
195
-
196
- function log( $message, $wrapper = false ) {
197
- $this->_log( $message, 'log', $wrapper );
198
- }
199
-
200
- function info( $message, $wrapper = false ) {
201
- $this->_log( $message, 'info', $wrapper );
202
- }
203
-
204
- function warn( $message, $wrapper = false ) {
205
- $this->_log( $message, 'warn', $wrapper );
206
- }
207
-
208
- function error( $message, $wrapper = false ) {
209
- $this->_log( $message, 'error', $wrapper );
210
- }
211
-
212
- /**
213
- * Log API error.
214
- *
215
- * @author Vova Feldman (@svovaf)
216
- * @since 1.2.1.5
217
- *
218
- * @param mixed $api_result
219
- * @param bool $wrapper
220
- */
221
- function api_error( $api_result, $wrapper = false ) {
222
- $message = '';
223
- if ( is_object( $api_result ) &&
224
- ! empty( $api_result->error ) &&
225
- ! empty( $api_result->error->message )
226
- ) {
227
- $message = $api_result->error->message;
228
- } else if ( is_object( $api_result ) ) {
229
- $message = var_export( $api_result, true );
230
- } else if ( is_string( $api_result ) ) {
231
- $message = $api_result;
232
- } else if ( empty( $api_result ) ) {
233
- $message = 'Empty API result.';
234
- }
235
-
236
- $message = 'API Error: ' . $message;
237
-
238
- $this->_log( $message, 'error', $wrapper );
239
- }
240
-
241
- function entrance( $message = '', $wrapper = false ) {
242
- $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message;
243
-
244
- $this->_log( $msg, 'log', $wrapper );
245
- }
246
-
247
- function departure( $message = '', $wrapper = false ) {
248
- $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message;
249
-
250
- $this->_log( $msg, 'log', $wrapper );
251
- }
252
-
253
- #--------------------------------------------------------------------------------
254
- #region Log Formatting
255
- #--------------------------------------------------------------------------------
256
-
257
- private static function format( $log, $show_type = true ) {
258
- return '[' . str_pad( $log['cnt'], strlen( self::$CNT ), '0', STR_PAD_LEFT ) . '] [' . $log['logger']->_id . '] ' . ( $show_type ? '[' . $log['log_type'] . ']' : '' ) . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . ' >> ' . $log['msg'] . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ') ' : '' ) . ' [' . $log['timestamp'] . ']';
259
- }
260
-
261
- private static function format_html( $log ) {
262
- return '<div style="font-size: 13px; font-family: monospace; color: #7da767; padding: 8px 3px; background: #000; border-bottom: 1px solid #555;">[' . $log['cnt'] . '] [' . $log['logger']->_id . '] [' . $log['log_type'] . '] <b><code style="color: #c4b1e0;">' . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . '</code> >> <b style="color: #f59330;">' . esc_html( $log['msg'] ) . '</b></b>' . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ')' : '' ) . ' [' . $log['timestamp'] . ']</div>';
263
- }
264
-
265
- #endregion
266
-
267
- static function dump() {
268
- ?>
269
- <!-- BEGIN: Freemius PHP Console Log -->
270
- <script type="text/javascript">
271
- <?php
272
- foreach ( self::$LOG as $log ) {
273
- echo 'console.' . $log['log_type'] . '(' . json_encode( self::format( $log, false ) ) . ')' . "\n";
274
- }
275
- ?>
276
- </script>
277
- <!-- END: Freemius PHP Console Log -->
278
- <?php
279
- }
280
-
281
- static function get_log() {
282
- return self::$LOG;
283
- }
284
-
285
- #--------------------------------------------------------------------------------
286
- #region Database Logging
287
- #--------------------------------------------------------------------------------
288
-
289
- /**
290
- * @author Vova Feldman (@svovaf)
291
- * @since 1.2.1.6
292
- *
293
- * @return bool
294
- */
295
- public static function is_storage_logging_on() {
296
- if ( ! isset( self::$_isStorageLoggingOn ) ) {
297
- self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
298
- }
299
-
300
- return self::$_isStorageLoggingOn;
301
- }
302
-
303
- /**
304
- * Turns on/off database persistent debugging to capture
305
- * multi-session logs to debug complex flows like
306
- * plugin auto-deactivate on premium version activation.
307
- *
308
- * @todo Check if Theme Check has issues with DB tables for themes.
309
- *
310
- * @author Vova Feldman (@svovaf)
311
- * @since 1.2.1.6
312
- *
313
- * @param bool $is_on
314
- *
315
- * @return bool
316
- */
317
- public static function _set_storage_logging( $is_on = true ) {
318
- global $wpdb;
319
-
320
- $table = "{$wpdb->prefix}fs_logger";
321
-
322
- if ( $is_on ) {
323
- /**
324
- * Create logging table.
325
- *
326
- * NOTE:
327
- * dbDelta must use KEY and not INDEX for indexes.
328
- *
329
- * @link https://core.trac.wordpress.org/ticket/2695
330
- */
331
- $result = $wpdb->query( "CREATE TABLE {$table} (
332
- `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
333
- `process_id` INT UNSIGNED NOT NULL,
334
- `user_name` VARCHAR(64) NOT NULL,
335
- `logger` VARCHAR(128) NOT NULL,
336
- `log_order` INT UNSIGNED NOT NULL,
337
- `type` ENUM('log','info','warn','error') NOT NULL DEFAULT 'log',
338
- `message` TEXT NOT NULL,
339
- `file` VARCHAR(256) NOT NULL,
340
- `line` INT UNSIGNED NOT NULL,
341
- `function` VARCHAR(256) NOT NULL,
342
- `request_type` ENUM('call','ajax','cron') NOT NULL DEFAULT 'call',
343
- `request_url` VARCHAR(1024) NOT NULL,
344
- `created` DECIMAL(16, 6) NOT NULL,
345
- PRIMARY KEY (`id`),
346
- KEY `process_id` (`process_id` ASC),
347
- KEY `process_logger` (`process_id` ASC, `logger` ASC),
348
- KEY `function` (`function` ASC),
349
- KEY `type` (`type` ASC))" );
350
- } else {
351
- /**
352
- * Drop logging table.
353
- */
354
- $result = $wpdb->query( "DROP TABLE IF EXISTS $table;" );
355
- }
356
-
357
- if ( false !== $result ) {
358
- update_option( 'fs_storage_logger', ( $is_on ? 1 : 0 ) );
359
- }
360
-
361
- return ( false !== $result );
362
- }
363
-
364
- /**
365
- * @author Vova Feldman (@svovaf)
366
- * @since 1.2.1.6
367
- *
368
- * @param string $type
369
- * @param string $message
370
- * @param int $log_order
371
- * @param array $caller
372
- *
373
- * @return false|int
374
- */
375
- private function db_log(
376
- &$type,
377
- &$message,
378
- &$log_order,
379
- &$caller
380
- ) {
381
- global $wpdb;
382
-
383
- $request_type = 'call';
384
- if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
385
- $request_type = 'cron';
386
- } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
387
- $request_type = 'ajax';
388
- }
389
-
390
- $request_url = WP_FS__IS_HTTP_REQUEST ?
391
- $_SERVER['REQUEST_URI'] :
392
- '';
393
-
394
- return $wpdb->insert(
395
- "{$wpdb->prefix}fs_logger",
396
- array(
397
- 'process_id' => self::$_processID,
398
- 'user_name' => self::$_ownerName,
399
- 'logger' => $this->_id,
400
- 'log_order' => $log_order,
401
- 'type' => $type,
402
- 'request_type' => $request_type,
403
- 'request_url' => $request_url,
404
- 'message' => $message,
405
- 'file' => isset( $caller['file'] ) ?
406
- substr( $caller['file'], self::$_abspathLength ) :
407
- '',
408
- 'line' => $caller['line'],
409
- 'function' => ( ! empty( $caller['class'] ) ? $caller['class'] . $caller['type'] : '' ) . $caller['function'],
410
- 'created' => microtime( true ),
411
- )
412
- );
413
- }
414
-
415
- /**
416
- * Persistent DB logger columns.
417
- *
418
- * @var array
419
- */
420
- private static $_log_columns = array(
421
- 'id',
422
- 'process_id',
423
- 'user_name',
424
- 'logger',
425
- 'log_order',
426
- 'type',
427
- 'message',
428
- 'file',
429
- 'line',
430
- 'function',
431
- 'request_type',
432
- 'request_url',
433
- 'created',
434
- );
435
-
436
- /**
437
- * Create DB logs query.
438
- *
439
- * @author Vova Feldman (@svovaf)
440
- * @since 1.2.1.6
441
- *
442
- * @param bool $filters
443
- * @param int $limit
444
- * @param int $offset
445
- * @param bool $order
446
- * @param bool $escape_eol
447
- *
448
- * @return string
449
- */
450
- private static function build_db_logs_query(
451
- $filters = false,
452
- $limit = 200,
453
- $offset = 0,
454
- $order = false,
455
- $escape_eol = false
456
- ) {
457
- global $wpdb;
458
-
459
- $select = '*';
460
-
461
- if ( $escape_eol ) {
462
- $select = '';
463
- for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
464
- if ( $i > 0 ) {
465
- $select .= ', ';
466
- }
467
-
468
- if ( 'message' !== self::$_log_columns[ $i ] ) {
469
- $select .= self::$_log_columns[ $i ];
470
- } else {
471
- $select .= 'REPLACE(message , \'\n\', \' \') AS message';
472
- }
473
- }
474
- }
475
-
476
- $query = "SELECT {$select} FROM {$wpdb->prefix}fs_logger";
477
- if ( is_array( $filters ) ) {
478
- $criteria = array();
479
-
480
- if ( ! empty( $filters['type'] ) && 'all' !== $filters['type'] ) {
481
- $filters['type'] = strtolower( $filters['type'] );
482
-
483
- switch ( $filters['type'] ) {
484
- case 'warn_error':
485
- $criteria[] = array( 'col' => 'type', 'val' => array( 'warn', 'error' ) );
486
- break;
487
- case 'error':
488
- case 'warn':
489
- $criteria[] = array( 'col' => 'type', 'val' => $filters['type'] );
490
- break;
491
- case 'info':
492
- default:
493
- $criteria[] = array( 'col' => 'type', 'val' => array( 'info', 'log' ) );
494
- break;
495
- }
496
- }
497
-
498
- if ( ! empty( $filters['request_type'] ) ) {
499
- $filters['request_type'] = strtolower( $filters['request_type'] );
500
-
501
- if ( in_array( $filters['request_type'], array( 'call', 'ajax', 'cron' ) ) ) {
502
- $criteria[] = array( 'col' => 'request_type', 'val' => $filters['request_type'] );
503
- }
504
- }
505
-
506
- if ( ! empty( $filters['file'] ) ) {
507
- $criteria[] = array(
508
- 'col' => 'file',
509
- 'op' => 'LIKE',
510
- 'val' => '%' . esc_sql( $filters['file'] ),
511
- );
512
- }
513
-
514
- if ( ! empty( $filters['function'] ) ) {
515
- $criteria[] = array(
516
- 'col' => 'function',
517
- 'op' => 'LIKE',
518
- 'val' => '%' . esc_sql( $filters['function'] ),
519
- );
520
- }
521
-
522
- if ( ! empty( $filters['process_id'] ) && is_numeric( $filters['process_id'] ) ) {
523
- $criteria[] = array( 'col' => 'process_id', 'val' => $filters['process_id'] );
524
- }
525
-
526
- if ( ! empty( $filters['logger'] ) ) {
527
- $criteria[] = array(
528
- 'col' => 'logger',
529
- 'op' => 'LIKE',
530
- 'val' => '%' . esc_sql( $filters['logger'] ) . '%',
531
- );
532
- }
533
-
534
- if ( ! empty( $filters['message'] ) ) {
535
- $criteria[] = array(
536
- 'col' => 'message',
537
- 'op' => 'LIKE',
538
- 'val' => '%' . esc_sql( $filters['message'] ) . '%',
539
- );
540
- }
541
-
542
- if ( 0 < count( $criteria ) ) {
543
- $query .= "\nWHERE\n";
544
-
545
- $first = true;
546
- foreach ( $criteria as $c ) {
547
- if ( ! $first ) {
548
- $query .= "AND\n";
549
- }
550
-
551
- if ( is_array( $c['val'] ) ) {
552
- $operator = 'IN';
553
-
554
- for ( $i = 0, $len = count( $c['val'] ); $i < $len; $i ++ ) {
555
- $c['val'][ $i ] = "'" . esc_sql( $c['val'][ $i ] ) . "'";
556
- }
557
-
558
- $val = '(' . implode( ',', $c['val'] ) . ')';
559
- } else {
560
- $operator = ! empty( $c['op'] ) ? $c['op'] : '=';
561
- $val = "'" . esc_sql( $c['val'] ) . "'";
562
- }
563
-
564
- $query .= "`{$c['col']}` {$operator} {$val}\n";
565
-
566
- $first = false;
567
- }
568
- }
569
- }
570
-
571
- if ( ! is_array( $order ) ) {
572
- $order = array(
573
- 'col' => 'id',
574
- 'order' => 'desc'
575
- );
576
- }
577
-
578
- $query .= " ORDER BY {$order['col']} {$order['order']} LIMIT {$offset},{$limit}";
579
-
580
- return $query;
581
- }
582
-
583
- /**
584
- * Load logs from DB.
585
- *
586
- * @author Vova Feldman (@svovaf)
587
- * @since 1.2.1.6
588
- *
589
- * @param bool $filters
590
- * @param int $limit
591
- * @param int $offset
592
- * @param bool $order
593
- *
594
- * @return object[]|null
595
- */
596
- public static function load_db_logs(
597
- $filters = false,
598
- $limit = 200,
599
- $offset = 0,
600
- $order = false
601
- ) {
602
- global $wpdb;
603
-
604
- $query = self::build_db_logs_query(
605
- $filters,
606
- $limit,
607
- $offset,
608
- $order
609
- );
610
-
611
- return $wpdb->get_results( $query );
612
- }
613
-
614
- /**
615
- * Load logs from DB.
616
- *
617
- * @author Vova Feldman (@svovaf)
618
- * @since 1.2.1.6
619
- *
620
- * @param bool $filters
621
- * @param string $filename
622
- * @param int $limit
623
- * @param int $offset
624
- * @param bool $order
625
- *
626
- * @return false|string File download URL or false on failure.
627
- */
628
- public static function download_db_logs(
629
- $filters = false,
630
- $filename = '',
631
- $limit = 10000,
632
- $offset = 0,
633
- $order = false
634
- ) {
635
- global $wpdb;
636
-
637
- $query = self::build_db_logs_query(
638
- $filters,
639
- $limit,
640
- $offset,
641
- $order,
642
- true
643
- );
644
-
645
- $upload_dir = wp_upload_dir();
646
- if ( empty( $filename ) ) {
647
- $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
648
- }
649
- $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
650
-
651
- $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY '\t' ESCAPED BY '\\\\' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n'";
652
-
653
- $columns = '';
654
- for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
655
- if ( $i > 0 ) {
656
- $columns .= ', ';
657
- }
658
-
659
- $columns .= "'" . self::$_log_columns[ $i ] . "'";
660
- }
661
-
662
- $query = "SELECT {$columns} UNION ALL " . $query;
663
-
664
- $result = $wpdb->query( $query );
665
-
666
- if ( false === $result ) {
667
- return false;
668
- }
669
-
670
- return rtrim( $upload_dir['url'], '/' ) . '/' . $filename;
671
- }
672
-
673
- /**
674
- * @author Vova Feldman (@svovaf)
675
- * @since 1.2.1.6
676
- *
677
- * @param string $filename
678
- *
679
- * @return string
680
- */
681
- public static function get_logs_download_url( $filename = '' ) {
682
- $upload_dir = wp_upload_dir();
683
- if ( empty( $filename ) ) {
684
- $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
685
- }
686
-
687
- return rtrim( $upload_dir['url'], '/' ) . $filename;
688
- }
689
-
690
- #endregion
691
- }
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2015, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.0.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Logger {
14
+ private $_id;
15
+ private $_on = false;
16
+ private $_echo = false;
17
+ private $_file_start = 0;
18
+ /**
19
+ * @var int PHP Process ID.
20
+ */
21
+ private static $_processID;
22
+ /**
23
+ * @var string PHP Script user name.
24
+ */
25
+ private static $_ownerName;
26
+ /**
27
+ * @var bool Is storage logging turned on.
28
+ */
29
+ private static $_isStorageLoggingOn;
30
+ /**
31
+ * @var int ABSPATH length.
32
+ */
33
+ private static $_abspathLength;
34
+
35
+ private static $LOGGERS = array();
36
+ private static $LOG = array();
37
+ private static $CNT = 0;
38
+ private static $_HOOKED_FOOTER = false;
39
+
40
+ private function __construct( $id, $on = false, $echo = false ) {
41
+ $this->_id = $id;
42
+
43
+ $bt = debug_backtrace();
44
+ $caller = $bt[2];
45
+
46
+ if ( false !== strpos( $caller['file'], 'plugins' ) ) {
47
+ $this->_file_start = strpos( $caller['file'], 'plugins' ) + strlen( 'plugins/' );
48
+ } else {
49
+ $this->_file_start = strpos( $caller['file'], 'themes' ) + strlen( 'themes/' );
50
+ }
51
+
52
+ if ( $on ) {
53
+ $this->on();
54
+ }
55
+ if ( $echo ) {
56
+ $this->echo_on();
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @param string $id
62
+ * @param bool $on
63
+ * @param bool $echo
64
+ *
65
+ * @return FS_Logger
66
+ */
67
+ public static function get_logger( $id, $on = false, $echo = false ) {
68
+ $id = strtolower( $id );
69
+
70
+ if ( ! isset( self::$_processID ) ) {
71
+ self::init();
72
+ }
73
+
74
+ if ( ! isset( self::$LOGGERS[ $id ] ) ) {
75
+ self::$LOGGERS[ $id ] = new FS_Logger( $id, $on, $echo );
76
+ }
77
+
78
+ return self::$LOGGERS[ $id ];
79
+ }
80
+
81
+ /**
82
+ * Initialize logging global info.
83
+ *
84
+ * @author Vova Feldman (@svovaf)
85
+ * @since 1.2.1.6
86
+ */
87
+ private static function init() {
88
+ self::$_ownerName = function_exists( 'get_current_user' ) ?
89
+ get_current_user() :
90
+ 'unknown';
91
+ self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
92
+ self::$_abspathLength = strlen( ABSPATH );
93
+ self::$_processID = mt_rand( 0, 32000 );
94
+
95
+ // Process ID may be `false` on errors.
96
+ if ( ! is_numeric( self::$_processID ) ) {
97
+ self::$_processID = 0;
98
+ }
99
+ }
100
+
101
+ private static function hook_footer() {
102
+ if ( self::$_HOOKED_FOOTER ) {
103
+ return;
104
+ }
105
+
106
+ if ( is_admin() ) {
107
+ add_action( 'admin_footer', 'FS_Logger::dump', 100 );
108
+ } else {
109
+ add_action( 'wp_footer', 'FS_Logger::dump', 100 );
110
+ }
111
+ }
112
+
113
+ function is_on() {
114
+ return $this->_on;
115
+ }
116
+
117
+ function on() {
118
+ $this->_on = true;
119
+
120
+ if ( ! function_exists( 'dbDelta' ) ) {
121
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
122
+ }
123
+
124
+ self::hook_footer();
125
+ }
126
+
127
+ function echo_on() {
128
+ $this->on();
129
+
130
+ $this->_echo = true;
131
+ }
132
+
133
+ function is_echo_on() {
134
+ return $this->_echo;
135
+ }
136
+
137
+ function get_id() {
138
+ return $this->_id;
139
+ }
140
+
141
+ function get_file() {
142
+ return $this->_file_start;
143
+ }
144
+
145
+ private function _log( &$message, $type, $wrapper = false ) {
146
+ if ( ! $this->is_on() ) {
147
+ return;
148
+ }
149
+
150
+ $bt = debug_backtrace();
151
+ $depth = $wrapper ? 3 : 2;
152
+ while ( $depth < count( $bt ) - 1 && 'eval' === $bt[ $depth ]['function'] ) {
153
+ $depth ++;
154
+ }
155
+
156
+ $caller = $bt[ $depth ];
157
+
158
+ /**
159
+ * Retrieve the correct call file & line number from backtrace
160
+ * when logging from a wrapper method.
161
+ *
162
+ * @author Vova Feldman
163
+ * @since 1.2.1.6
164
+ */
165
+ if ( empty( $caller['line'] ) ) {
166
+ $depth --;
167
+
168
+ while ( $depth >= 0 ) {
169
+ if ( ! empty( $bt[ $depth ]['line'] ) ) {
170
+ $caller['line'] = $bt[ $depth ]['line'];
171
+ $caller['file'] = $bt[ $depth ]['file'];
172
+ break;
173
+ }
174
+ }
175
+ }
176
+
177
+ $log = array_merge( $caller, array(
178
+ 'cnt' => self::$CNT ++,
179
+ 'logger' => $this,
180
+ 'timestamp' => microtime( true ),
181
+ 'log_type' => $type,
182
+ 'msg' => $message,
183
+ ) );
184
+
185
+ if ( self::$_isStorageLoggingOn ) {
186
+ $this->db_log( $type, $message, self::$CNT, $caller );
187
+ }
188
+
189
+ self::$LOG[] = $log;
190
+
191
+ if ( $this->is_echo_on() && ! Freemius::is_ajax() ) {
192
+ echo self::format_html( $log ) . "\n";
193
+ }
194
+ }
195
+
196
+ function log( $message, $wrapper = false ) {
197
+ $this->_log( $message, 'log', $wrapper );
198
+ }
199
+
200
+ function info( $message, $wrapper = false ) {
201
+ $this->_log( $message, 'info', $wrapper );
202
+ }
203
+
204
+ function warn( $message, $wrapper = false ) {
205
+ $this->_log( $message, 'warn', $wrapper );
206
+ }
207
+
208
+ function error( $message, $wrapper = false ) {
209
+ $this->_log( $message, 'error', $wrapper );
210
+ }
211
+
212
+ /**
213
+ * Log API error.
214
+ *
215
+ * @author Vova Feldman (@svovaf)
216
+ * @since 1.2.1.5
217
+ *
218
+ * @param mixed $api_result
219
+ * @param bool $wrapper
220
+ */
221
+ function api_error( $api_result, $wrapper = false ) {
222
+ $message = '';
223
+ if ( is_object( $api_result ) &&
224
+ ! empty( $api_result->error ) &&
225
+ ! empty( $api_result->error->message )
226
+ ) {
227
+ $message = $api_result->error->message;
228
+ } else if ( is_object( $api_result ) ) {
229
+ $message = var_export( $api_result, true );
230
+ } else if ( is_string( $api_result ) ) {
231
+ $message = $api_result;
232
+ } else if ( empty( $api_result ) ) {
233
+ $message = 'Empty API result.';
234
+ }
235
+
236
+ $message = 'API Error: ' . $message;
237
+
238
+ $this->_log( $message, 'error', $wrapper );
239
+ }
240
+
241
+ function entrance( $message = '', $wrapper = false ) {
242
+ $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message;
243
+
244
+ $this->_log( $msg, 'log', $wrapper );
245
+ }
246
+
247
+ function departure( $message = '', $wrapper = false ) {
248
+ $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message;
249
+
250
+ $this->_log( $msg, 'log', $wrapper );
251
+ }
252
+
253
+ #--------------------------------------------------------------------------------
254
+ #region Log Formatting
255
+ #--------------------------------------------------------------------------------
256
+
257
+ private static function format( $log, $show_type = true ) {
258
+ return '[' . str_pad( $log['cnt'], strlen( self::$CNT ), '0', STR_PAD_LEFT ) . '] [' . $log['logger']->_id . '] ' . ( $show_type ? '[' . $log['log_type'] . ']' : '' ) . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . ' >> ' . $log['msg'] . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ') ' : '' ) . ' [' . $log['timestamp'] . ']';
259
+ }
260
+
261
+ private static function format_html( $log ) {
262
+ return '<div style="font-size: 13px; font-family: monospace; color: #7da767; padding: 8px 3px; background: #000; border-bottom: 1px solid #555;">[' . $log['cnt'] . '] [' . $log['logger']->_id . '] [' . $log['log_type'] . '] <b><code style="color: #c4b1e0;">' . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . '</code> >> <b style="color: #f59330;">' . esc_html( $log['msg'] ) . '</b></b>' . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ')' : '' ) . ' [' . $log['timestamp'] . ']</div>';
263
+ }
264
+
265
+ #endregion
266
+
267
+ static function dump() {
268
+ ?>
269
+ <!-- BEGIN: Freemius PHP Console Log -->
270
+ <script type="text/javascript">
271
+ <?php
272
+ foreach ( self::$LOG as $log ) {
273
+ echo 'console.' . $log['log_type'] . '(' . json_encode( self::format( $log, false ) ) . ')' . "\n";
274
+ }
275
+ ?>
276
+ </script>
277
+ <!-- END: Freemius PHP Console Log -->
278
+ <?php
279
+ }
280
+
281
+ static function get_log() {
282
+ return self::$LOG;
283
+ }
284
+
285
+ #--------------------------------------------------------------------------------
286
+ #region Database Logging
287
+ #--------------------------------------------------------------------------------
288
+
289
+ /**
290
+ * @author Vova Feldman (@svovaf)
291
+ * @since 1.2.1.6
292
+ *
293
+ * @return bool
294
+ */
295
+ public static function is_storage_logging_on() {
296
+ if ( ! isset( self::$_isStorageLoggingOn ) ) {
297
+ self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
298
+ }
299
+
300
+ return self::$_isStorageLoggingOn;
301
+ }
302
+
303
+ /**
304
+ * Turns on/off database persistent debugging to capture
305
+ * multi-session logs to debug complex flows like
306
+ * plugin auto-deactivate on premium version activation.
307
+ *
308
+ * @todo Check if Theme Check has issues with DB tables for themes.
309
+ *
310
+ * @author Vova Feldman (@svovaf)
311
+ * @since 1.2.1.6
312
+ *
313
+ * @param bool $is_on
314
+ *
315
+ * @return bool
316
+ */
317
+ public static function _set_storage_logging( $is_on = true ) {
318
+ global $wpdb;
319
+
320
+ $table = "{$wpdb->prefix}fs_logger";
321
+
322
+ if ( $is_on ) {
323
+ /**
324
+ * Create logging table.
325
+ *
326
+ * NOTE:
327
+ * dbDelta must use KEY and not INDEX for indexes.
328
+ *
329
+ * @link https://core.trac.wordpress.org/ticket/2695
330
+ */
331
+ $result = $wpdb->query( "CREATE TABLE {$table} (
332
+ `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
333
+ `process_id` INT UNSIGNED NOT NULL,
334
+ `user_name` VARCHAR(64) NOT NULL,
335
+ `logger` VARCHAR(128) NOT NULL,
336
+ `log_order` INT UNSIGNED NOT NULL,
337
+ `type` ENUM('log','info','warn','error') NOT NULL DEFAULT 'log',
338
+ `message` TEXT NOT NULL,
339
+ `file` VARCHAR(256) NOT NULL,
340
+ `line` INT UNSIGNED NOT NULL,
341
+ `function` VARCHAR(256) NOT NULL,
342
+ `request_type` ENUM('call','ajax','cron') NOT NULL DEFAULT 'call',
343
+ `request_url` VARCHAR(1024) NOT NULL,
344
+ `created` DECIMAL(16, 6) NOT NULL,
345
+ PRIMARY KEY (`id`),
346
+ KEY `process_id` (`process_id` ASC),
347
+ KEY `process_logger` (`process_id` ASC, `logger` ASC),
348
+ KEY `function` (`function` ASC),
349
+ KEY `type` (`type` ASC))" );
350
+ } else {
351
+ /**
352
+ * Drop logging table.
353
+ */
354
+ $result = $wpdb->query( "DROP TABLE IF EXISTS $table;" );
355
+ }
356
+
357
+ if ( false !== $result ) {
358
+ update_option( 'fs_storage_logger', ( $is_on ? 1 : 0 ) );
359
+ }
360
+
361
+ return ( false !== $result );
362
+ }
363
+
364
+ /**
365
+ * @author Vova Feldman (@svovaf)
366
+ * @since 1.2.1.6
367
+ *
368
+ * @param string $type
369
+ * @param string $message
370
+ * @param int $log_order
371
+ * @param array $caller
372
+ *
373
+ * @return false|int
374
+ */
375
+ private function db_log(
376
+ &$type,
377
+ &$message,
378
+ &$log_order,
379
+ &$caller
380
+ ) {
381
+ global $wpdb;
382
+
383
+ $request_type = 'call';
384
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
385
+ $request_type = 'cron';
386
+ } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
387
+ $request_type = 'ajax';
388
+ }
389
+
390
+ $request_url = WP_FS__IS_HTTP_REQUEST ?
391
+ $_SERVER['REQUEST_URI'] :
392
+ '';
393
+
394
+ return $wpdb->insert(
395
+ "{$wpdb->prefix}fs_logger",
396
+ array(
397
+ 'process_id' => self::$_processID,
398
+ 'user_name' => self::$_ownerName,
399
+ 'logger' => $this->_id,
400
+ 'log_order' => $log_order,
401
+ 'type' => $type,
402
+ 'request_type' => $request_type,
403
+ 'request_url' => $request_url,
404
+ 'message' => $message,
405
+ 'file' => isset( $caller['file'] ) ?
406
+ substr( $caller['file'], self::$_abspathLength ) :
407
+ '',
408
+ 'line' => $caller['line'],
409
+ 'function' => ( ! empty( $caller['class'] ) ? $caller['class'] . $caller['type'] : '' ) . $caller['function'],
410
+ 'created' => microtime( true ),
411
+ )
412
+ );
413
+ }
414
+
415
+ /**
416
+ * Persistent DB logger columns.
417
+ *
418
+ * @var array
419
+ */
420
+ private static $_log_columns = array(
421
+ 'id',
422
+ 'process_id',
423
+ 'user_name',
424
+ 'logger',
425
+ 'log_order',
426
+ 'type',
427
+ 'message',
428
+ 'file',
429
+ 'line',
430
+ 'function',
431
+ 'request_type',
432
+ 'request_url',
433
+ 'created',
434
+ );
435
+
436
+ /**
437
+ * Create DB logs query.
438
+ *
439
+ * @author Vova Feldman (@svovaf)
440
+ * @since 1.2.1.6
441
+ *
442
+ * @param bool $filters
443
+ * @param int $limit
444
+ * @param int $offset
445
+ * @param bool $order
446
+ * @param bool $escape_eol
447
+ *
448
+ * @return string
449
+ */
450
+ private static function build_db_logs_query(
451
+ $filters = false,
452
+ $limit = 200,
453
+ $offset = 0,
454
+ $order = false,
455
+ $escape_eol = false
456
+ ) {
457
+ global $wpdb;
458
+
459
+ $select = '*';
460
+
461
+ if ( $escape_eol ) {
462
+ $select = '';
463
+ for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
464
+ if ( $i > 0 ) {
465
+ $select .= ', ';
466
+ }
467
+
468
+ if ( 'message' !== self::$_log_columns[ $i ] ) {
469
+ $select .= self::$_log_columns[ $i ];
470
+ } else {
471
+ $select .= 'REPLACE(message , \'\n\', \' \') AS message';
472
+ }
473
+ }
474
+ }
475
+
476
+ $query = "SELECT {$select} FROM {$wpdb->prefix}fs_logger";
477
+ if ( is_array( $filters ) ) {
478
+ $criteria = array();
479
+
480
+ if ( ! empty( $filters['type'] ) && 'all' !== $filters['type'] ) {
481
+ $filters['type'] = strtolower( $filters['type'] );
482
+
483
+ switch ( $filters['type'] ) {
484
+ case 'warn_error':
485
+ $criteria[] = array( 'col' => 'type', 'val' => array( 'warn', 'error' ) );
486
+ break;
487
+ case 'error':
488
+ case 'warn':
489
+ $criteria[] = array( 'col' => 'type', 'val' => $filters['type'] );
490
+ break;
491
+ case 'info':
492
+ default:
493
+ $criteria[] = array( 'col' => 'type', 'val' => array( 'info', 'log' ) );
494
+ break;
495
+ }
496
+ }
497
+
498
+ if ( ! empty( $filters['request_type'] ) ) {
499
+ $filters['request_type'] = strtolower( $filters['request_type'] );
500
+
501
+ if ( in_array( $filters['request_type'], array( 'call', 'ajax', 'cron' ) ) ) {
502
+ $criteria[] = array( 'col' => 'request_type', 'val' => $filters['request_type'] );
503
+ }
504
+ }
505
+
506
+ if ( ! empty( $filters['file'] ) ) {
507
+ $criteria[] = array(
508
+ 'col' => 'file',
509
+ 'op' => 'LIKE',
510
+ 'val' => '%' . esc_sql( $filters['file'] ),
511
+ );
512
+ }
513
+
514
+ if ( ! empty( $filters['function'] ) ) {
515
+ $criteria[] = array(
516
+ 'col' => 'function',
517
+ 'op' => 'LIKE',
518
+ 'val' => '%' . esc_sql( $filters['function'] ),
519
+ );
520
+ }
521
+
522
+ if ( ! empty( $filters['process_id'] ) && is_numeric( $filters['process_id'] ) ) {
523
+ $criteria[] = array( 'col' => 'process_id', 'val' => $filters['process_id'] );
524
+ }
525
+
526
+ if ( ! empty( $filters['logger'] ) ) {
527
+ $criteria[] = array(
528
+ 'col' => 'logger',
529
+ 'op' => 'LIKE',
530
+ 'val' => '%' . esc_sql( $filters['logger'] ) . '%',
531
+ );
532
+ }
533
+
534
+ if ( ! empty( $filters['message'] ) ) {
535
+ $criteria[] = array(
536
+ 'col' => 'message',
537
+ 'op' => 'LIKE',
538
+ 'val' => '%' . esc_sql( $filters['message'] ) . '%',
539
+ );
540
+ }
541
+
542
+ if ( 0 < count( $criteria ) ) {
543
+ $query .= "\nWHERE\n";
544
+
545
+ $first = true;
546
+ foreach ( $criteria as $c ) {
547
+ if ( ! $first ) {
548
+ $query .= "AND\n";
549
+ }
550
+
551
+ if ( is_array( $c['val'] ) ) {
552
+ $operator = 'IN';
553
+
554
+ for ( $i = 0, $len = count( $c['val'] ); $i < $len; $i ++ ) {
555
+ $c['val'][ $i ] = "'" . esc_sql( $c['val'][ $i ] ) . "'";
556
+ }
557
+
558
+ $val = '(' . implode( ',', $c['val'] ) . ')';
559
+ } else {
560
+ $operator = ! empty( $c['op'] ) ? $c['op'] : '=';
561
+ $val = "'" . esc_sql( $c['val'] ) . "'";
562
+ }
563
+
564
+ $query .= "`{$c['col']}` {$operator} {$val}\n";
565
+
566
+ $first = false;
567
+ }
568
+ }
569
+ }
570
+
571
+ if ( ! is_array( $order ) ) {
572
+ $order = array(
573
+ 'col' => 'id',
574
+ 'order' => 'desc'
575
+ );
576
+ }
577
+
578
+ $query .= " ORDER BY {$order['col']} {$order['order']} LIMIT {$offset},{$limit}";
579
+
580
+ return $query;
581
+ }
582
+
583
+ /**
584
+ * Load logs from DB.
585
+ *
586
+ * @author Vova Feldman (@svovaf)
587
+ * @since 1.2.1.6
588
+ *
589
+ * @param bool $filters
590
+ * @param int $limit
591
+ * @param int $offset
592
+ * @param bool $order
593
+ *
594
+ * @return object[]|null
595
+ */
596
+ public static function load_db_logs(
597
+ $filters = false,
598
+ $limit = 200,
599
+ $offset = 0,
600
+ $order = false
601
+ ) {
602
+ global $wpdb;
603
+
604
+ $query = self::build_db_logs_query(
605
+ $filters,
606
+ $limit,
607
+ $offset,
608
+ $order
609
+ );
610
+
611
+ return $wpdb->get_results( $query );
612
+ }
613
+
614
+ /**
615
+ * Load logs from DB.
616
+ *
617
+ * @author Vova Feldman (@svovaf)
618
+ * @since 1.2.1.6
619
+ *
620
+ * @param bool $filters
621
+ * @param string $filename
622
+ * @param int $limit
623
+ * @param int $offset
624
+ * @param bool $order
625
+ *
626
+ * @return false|string File download URL or false on failure.
627
+ */
628
+ public static function download_db_logs(
629
+ $filters = false,
630
+ $filename = '',
631
+ $limit = 10000,
632
+ $offset = 0,
633
+ $order = false
634
+ ) {
635
+ global $wpdb;
636
+
637
+ $query = self::build_db_logs_query(
638
+ $filters,
639
+ $limit,
640
+ $offset,
641
+ $order,
642
+ true
643
+ );
644
+
645
+ $upload_dir = wp_upload_dir();
646
+ if ( empty( $filename ) ) {
647
+ $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
648
+ }
649
+ $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
650
+
651
+ $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY '\t' ESCAPED BY '\\\\' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n'";
652
+
653
+ $columns = '';
654
+ for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
655
+ if ( $i > 0 ) {
656
+ $columns .= ', ';
657
+ }
658
+
659
+ $columns .= "'" . self::$_log_columns[ $i ] . "'";
660
+ }
661
+
662
+ $query = "SELECT {$columns} UNION ALL " . $query;
663
+
664
+ $result = $wpdb->query( $query );
665
+
666
+ if ( false === $result ) {
667
+ return false;
668
+ }
669
+
670
+ return rtrim( $upload_dir['url'], '/' ) . '/' . $filename;
671
+ }
672
+
673
+ /**
674
+ * @author Vova Feldman (@svovaf)
675
+ * @since 1.2.1.6
676
+ *
677
+ * @param string $filename
678
+ *
679
+ * @return string
680
+ */
681
+ public static function get_logs_download_url( $filename = '' ) {
682
+ $upload_dir = wp_upload_dir();
683
+ if ( empty( $filename ) ) {
684
+ $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
685
+ }
686
+
687
+ return rtrim( $upload_dir['url'], '/' ) . $filename;
688
+ }
689
+
690
+ #endregion
691
+ }
freemius/includes/entities/class-fs-site.php CHANGED
@@ -1,236 +1,253 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2015, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.0.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Site extends FS_Scope_Entity {
14
- /**
15
- * @var number
16
- */
17
- public $site_id;
18
- /**
19
- * @var number
20
- */
21
- public $plugin_id;
22
- /**
23
- * @var number
24
- */
25
- public $user_id;
26
- /**
27
- * @var string
28
- */
29
- public $title;
30
- /**
31
- * @var string
32
- */
33
- public $url;
34
- /**
35
- * @var string
36
- */
37
- public $version;
38
- /**
39
- * @var string E.g. en-GB
40
- */
41
- public $language;
42
- /**
43
- * @var string E.g. UTF-8
44
- */
45
- public $charset;
46
- /**
47
- * @var string Platform version (e.g WordPress version).
48
- */
49
- public $platform_version;
50
- /**
51
- * Freemius SDK version
52
- *
53
- * @author Leo Fajardo (@leorw)
54
- * @since 1.2.2
55
- *
56
- * @var string SDK version (e.g.: 1.2.2)
57
- */
58
- public $sdk_version;
59
- /**
60
- * @var string Programming language version (e.g PHP version).
61
- */
62
- public $programming_language_version;
63
- /**
64
- * @var number|null
65
- */
66
- public $plan_id;
67
- /**
68
- * @var number|null
69
- */
70
- public $license_id;
71
- /**
72
- * @var number|null
73
- */
74
- public $trial_plan_id;
75
- /**
76
- * @var string|null
77
- */
78
- public $trial_ends;
79
- /**
80
- * @since 1.0.9
81
- *
82
- * @var bool
83
- */
84
- public $is_premium = false;
85
- /**
86
- * @author Leo Fajardo (@leorw)
87
- *
88
- * @since 1.2.1.5
89
- *
90
- * @var bool
91
- */
92
- public $is_disconnected = false;
93
- /**
94
- * @since 2.0.0
95
- *
96
- * @var bool
97
- */
98
- public $is_active = true;
99
- /**
100
- * @since 2.0.0
101
- *
102
- * @var bool
103
- */
104
- public $is_uninstalled = false;
105
-
106
- /**
107
- * @param stdClass|bool $site
108
- */
109
- function __construct( $site = false ) {
110
- parent::__construct( $site );
111
-
112
- if ( is_object( $site ) ) {
113
- $this->plan_id = $site->plan_id;
114
- }
115
-
116
- if ( ! is_bool( $this->is_disconnected ) ) {
117
- $this->is_disconnected = false;
118
- }
119
- }
120
-
121
- static function get_type() {
122
- return 'install';
123
- }
124
-
125
- /**
126
- * @author Vova Feldman (@svovaf)
127
- * @since 2.0.0
128
- *
129
- * @param string $url
130
- *
131
- * @return bool
132
- */
133
- static function is_localhost_by_address( $url ) {
134
- if ( false !== strpos( $url, '127.0.0.1' ) ||
135
- false !== strpos( $url, 'localhost' )
136
- ) {
137
- return true;
138
- }
139
-
140
- if ( ! fs_starts_with( $url, 'http' ) ) {
141
- $url = 'http://' . $url;
142
- }
143
-
144
- $url_parts = parse_url( $url );
145
-
146
- $subdomain = $url_parts['host'];
147
-
148
- return (
149
- // Starts with.
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.
157
- fs_ends_with( $subdomain, '.dev' ) ||
158
- fs_ends_with( $subdomain, '.test' ) ||
159
- fs_ends_with( $subdomain, '.staging' ) ||
160
- fs_ends_with( $subdomain, '.local' ) ||
161
- fs_ends_with( $subdomain, '.example' ) ||
162
- fs_ends_with( $subdomain, '.invalid' ) ||
163
- // GoDaddy test/dev.
164
- fs_ends_with( $subdomain, '.myftpupload.com' ) ||
165
- // ngrok tunneling.
166
- fs_ends_with( $subdomain, '.ngrok.io' ) ||
167
- // wpsandbox.
168
- fs_ends_with( $subdomain, '.wpsandbox.pro' ) ||
169
- // SiteGround staging.
170
- fs_starts_with( $subdomain, 'staging' ) ||
171
- // WPEngine staging.
172
- fs_ends_with( $subdomain, '.staging.wpengine.com' ) ||
173
- fs_ends_with( $subdomain, '.dev.wpengine.com' ) ||
174
- fs_ends_with( $subdomain, '.wpengine.com' ) ||
175
- // Pantheon
176
- ( fs_ends_with( $subdomain, 'pantheonsite.io' ) &&
177
- ( fs_starts_with( $subdomain, 'test-' ) || fs_starts_with( $subdomain, 'dev-' ) ) ) ||
178
- // Cloudways
179
- fs_ends_with( $subdomain, '.cloudwaysapps.com' ) ||
180
- // Kinsta
181
- ( fs_starts_with( $subdomain, 'staging-' ) && ( fs_ends_with( $subdomain, '.kinsta.com' ) || fs_ends_with( $subdomain, '.kinsta.cloud' ) ) ) ||
182
- // DesktopServer
183
- fs_ends_with( $subdomain, '.dev.cc' ) ||
184
- // Pressable
185
- fs_ends_with( $subdomain, '.mystagingwebsite.com' )
186
- );
187
- }
188
-
189
- function is_localhost() {
190
- return ( WP_FS__IS_LOCALHOST_FOR_SERVER || self::is_localhost_by_address( $this->url ) );
191
- }
192
-
193
- /**
194
- * Check if site in trial.
195
- *
196
- * @author Vova Feldman (@svovaf)
197
- * @since 1.0.9
198
- *
199
- * @return bool
200
- */
201
- function is_trial() {
202
- return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME );
203
- }
204
-
205
- /**
206
- * Check if user already utilized the trial with the current install.
207
- *
208
- * @author Vova Feldman (@svovaf)
209
- * @since 1.0.9
210
- *
211
- * @return bool
212
- */
213
- function is_trial_utilized() {
214
- return is_numeric( $this->trial_plan_id );
215
- }
216
-
217
- /**
218
- * @author Vova Feldman (@svovaf)
219
- * @since 2.0.0
220
- *
221
- * @return bool
222
- */
223
- function is_tracking_allowed() {
224
- return ( true !== $this->is_disconnected );
225
- }
226
-
227
- /**
228
- * @author Vova Feldman (@svovaf)
229
- * @since 2.0.0
230
- *
231
- * @return bool
232
- */
233
- function is_tracking_prohibited() {
234
- return ! $this->is_tracking_allowed();
235
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2015, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.0.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Site extends FS_Scope_Entity {
14
+ /**
15
+ * @var number
16
+ */
17
+ public $site_id;
18
+ /**
19
+ * @var number
20
+ */
21
+ public $plugin_id;
22
+ /**
23
+ * @var number
24
+ */
25
+ public $user_id;
26
+ /**
27
+ * @var string
28
+ */
29
+ public $title;
30
+ /**
31
+ * @var string
32
+ */
33
+ public $url;
34
+ /**
35
+ * @var string
36
+ */
37
+ public $version;
38
+ /**
39
+ * @var string E.g. en-GB
40
+ */
41
+ public $language;
42
+ /**
43
+ * @var string E.g. UTF-8
44
+ */
45
+ public $charset;
46
+ /**
47
+ * @var string Platform version (e.g WordPress version).
48
+ */
49
+ public $platform_version;
50
+ /**
51
+ * Freemius SDK version
52
+ *
53
+ * @author Leo Fajardo (@leorw)
54
+ * @since 1.2.2
55
+ *
56
+ * @var string SDK version (e.g.: 1.2.2)
57
+ */
58
+ public $sdk_version;
59
+ /**
60
+ * @var string Programming language version (e.g PHP version).
61
+ */
62
+ public $programming_language_version;
63
+ /**
64
+ * @var number|null
65
+ */
66
+ public $plan_id;
67
+ /**
68
+ * @var number|null
69
+ */
70
+ public $license_id;
71
+ /**
72
+ * @var number|null
73
+ */
74
+ public $trial_plan_id;
75
+ /**
76
+ * @var string|null
77
+ */
78
+ public $trial_ends;
79
+ /**
80
+ * @since 1.0.9
81
+ *
82
+ * @var bool
83
+ */
84
+ public $is_premium = false;
85
+ /**
86
+ * @author Leo Fajardo (@leorw)
87
+ *
88
+ * @since 1.2.1.5
89
+ *
90
+ * @var bool
91
+ */
92
+ public $is_disconnected = false;
93
+ /**
94
+ * @since 2.0.0
95
+ *
96
+ * @var bool
97
+ */
98
+ public $is_active = true;
99
+ /**
100
+ * @since 2.0.0
101
+ *
102
+ * @var bool
103
+ */
104
+ public $is_uninstalled = false;
105
+ /**
106
+ * @author Edgar Melkonyan
107
+ *
108
+ * @since 2.4.2
109
+ *
110
+ * @var bool
111
+ */
112
+ public $is_beta;
113
+
114
+ /**
115
+ * @param stdClass|bool $site
116
+ */
117
+ function __construct( $site = false ) {
118
+ parent::__construct( $site );
119
+
120
+ if ( is_object( $site ) ) {
121
+ $this->plan_id = $site->plan_id;
122
+ }
123
+
124
+ if ( ! is_bool( $this->is_disconnected ) ) {
125
+ $this->is_disconnected = false;
126
+ }
127
+ }
128
+
129
+ static function get_type() {
130
+ return 'install';
131
+ }
132
+
133
+ /**
134
+ * @author Vova Feldman (@svovaf)
135
+ * @since 2.0.0
136
+ *
137
+ * @param string $url
138
+ *
139
+ * @return bool
140
+ */
141
+ static function is_localhost_by_address( $url ) {
142
+ if ( false !== strpos( $url, '127.0.0.1' ) ||
143
+ false !== strpos( $url, 'localhost' )
144
+ ) {
145
+ return true;
146
+ }
147
+
148
+ if ( ! fs_starts_with( $url, 'http' ) ) {
149
+ $url = 'http://' . $url;
150
+ }
151
+
152
+ $url_parts = parse_url( $url );
153
+
154
+ $subdomain = $url_parts['host'];
155
+
156
+ return (
157
+ // Starts with.
158
+ fs_starts_with( $subdomain, 'local.' ) ||
159
+ fs_starts_with( $subdomain, 'dev.' ) ||
160
+ fs_starts_with( $subdomain, 'test.' ) ||
161
+ fs_starts_with( $subdomain, 'stage.' ) ||
162
+ fs_starts_with( $subdomain, 'staging.' ) ||
163
+
164
+ // Ends with.
165
+ fs_ends_with( $subdomain, '.dev' ) ||
166
+ fs_ends_with( $subdomain, '.test' ) ||
167
+ fs_ends_with( $subdomain, '.staging' ) ||
168
+ fs_ends_with( $subdomain, '.local' ) ||
169
+ fs_ends_with( $subdomain, '.example' ) ||
170
+ fs_ends_with( $subdomain, '.invalid' ) ||
171
+ // GoDaddy test/dev.
172
+ fs_ends_with( $subdomain, '.myftpupload.com' ) ||
173
+ // ngrok tunneling.
174
+ fs_ends_with( $subdomain, '.ngrok.io' ) ||
175
+ // wpsandbox.
176
+ fs_ends_with( $subdomain, '.wpsandbox.pro' ) ||
177
+ // SiteGround staging.
178
+ fs_starts_with( $subdomain, 'staging' ) ||
179
+ // WPEngine staging.
180
+ fs_ends_with( $subdomain, '.staging.wpengine.com' ) ||
181
+ fs_ends_with( $subdomain, '.dev.wpengine.com' ) ||
182
+ fs_ends_with( $subdomain, '.wpengine.com' ) ||
183
+ // Pantheon
184
+ ( fs_ends_with( $subdomain, 'pantheonsite.io' ) &&
185
+ ( fs_starts_with( $subdomain, 'test-' ) || fs_starts_with( $subdomain, 'dev-' ) ) ) ||
186
+ // Cloudways
187
+ fs_ends_with( $subdomain, '.cloudwaysapps.com' ) ||
188
+ // Kinsta
189
+ ( fs_starts_with( $subdomain, 'staging-' ) && ( fs_ends_with( $subdomain, '.kinsta.com' ) || fs_ends_with( $subdomain, '.kinsta.cloud' ) ) ) ||
190
+ // DesktopServer
191
+ fs_ends_with( $subdomain, '.dev.cc' ) ||
192
+ // Pressable
193
+ fs_ends_with( $subdomain, '.mystagingwebsite.com' )
194
+ );
195
+ }
196
+
197
+ function is_localhost() {
198
+ return ( WP_FS__IS_LOCALHOST_FOR_SERVER || self::is_localhost_by_address( $this->url ) );
199
+ }
200
+
201
+ /**
202
+ * Check if site in trial.
203
+ *
204
+ * @author Vova Feldman (@svovaf)
205
+ * @since 1.0.9
206
+ *
207
+ * @return bool
208
+ */
209
+ function is_trial() {
210
+ return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME );
211
+ }
212
+
213
+ /**
214
+ * Check if user already utilized the trial with the current install.
215
+ *
216
+ * @author Vova Feldman (@svovaf)
217
+ * @since 1.0.9
218
+ *
219
+ * @return bool
220
+ */
221
+ function is_trial_utilized() {
222
+ return is_numeric( $this->trial_plan_id );
223
+ }
224
+
225
+ /**
226
+ * @author Vova Feldman (@svovaf)
227
+ * @since 2.0.0
228
+ *
229
+ * @return bool
230
+ */
231
+ function is_tracking_allowed() {
232
+ return ( true !== $this->is_disconnected );
233
+ }
234
+
235
+ /**
236
+ * @author Vova Feldman (@svovaf)
237
+ * @since 2.0.0
238
+ *
239
+ * @return bool
240
+ */
241
+ function is_tracking_prohibited() {
242
+ return ! $this->is_tracking_allowed();
243
+ }
244
+
245
+ /**
246
+ * @author Edgar Melkonyan
247
+ *
248
+ * @return bool
249
+ */
250
+ function is_beta() {
251
+ return ( isset( $this->is_beta ) && true === $this->is_beta );
252
+ }
253
  }
freemius/includes/entities/class-fs-user.php CHANGED
@@ -1,79 +1,62 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2015, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.0.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_User extends FS_Scope_Entity {
14
-
15
- #region Properties
16
-
17
- /**
18
- * @var string
19
- */
20
- public $email;
21
- /**
22
- * @var string
23
- */
24
- public $first;
25
- /**
26
- * @var string
27
- */
28
- public $last;
29
- /**
30
- * @var bool
31
- */
32
- public $is_verified;
33
- /**
34
- * @author Leo Fajardo (@leorw)
35
- * @since 2.3.0
36
- *
37
- * @var bool
38
- */
39
- public $is_beta;
40
- /**
41
- * @var string|null
42
- */
43
- public $customer_id;
44
- /**
45
- * @var float
46
- */
47
- public $gross;
48
-
49
- #endregion Properties
50
-
51
- /**
52
- * @param object|bool $user
53
- */
54
- function __construct( $user = false ) {
55
- parent::__construct( $user );
56
- }
57
-
58
- function get_name() {
59
- return trim( ucfirst( trim( is_string( $this->first ) ? $this->first : '' ) ) . ' ' . ucfirst( trim( is_string( $this->last ) ? $this->last : '' ) ) );
60
- }
61
-
62
- function is_verified() {
63
- return ( isset( $this->is_verified ) && true === $this->is_verified );
64
- }
65
-
66
- /**
67
- * @author Leo Fajardo (@leorw)
68
- * @since 2.3.0
69
- *
70
- * @return bool
71
- */
72
- function is_beta() {
73
- return ( isset( $this->is_beta ) && true === $this->is_beta );
74
- }
75
-
76
- static function get_type() {
77
- return 'user';
78
- }
79
  }
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2015, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.0.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_User extends FS_Scope_Entity {
14
+
15
+ #region Properties
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ public $email;
21
+ /**
22
+ * @var string
23
+ */
24
+ public $first;
25
+ /**
26
+ * @var string
27
+ */
28
+ public $last;
29
+ /**
30
+ * @var bool
31
+ */
32
+ public $is_verified;
33
+ /**
34
+ * @var string|null
35
+ */
36
+ public $customer_id;
37
+ /**
38
+ * @var float
39
+ */
40
+ public $gross;
41
+
42
+ #endregion Properties
43
+
44
+ /**
45
+ * @param object|bool $user
46
+ */
47
+ function __construct( $user = false ) {
48
+ parent::__construct( $user );
49
+ }
50
+
51
+ function get_name() {
52
+ return trim( ucfirst( trim( is_string( $this->first ) ? $this->first : '' ) ) . ' ' . ucfirst( trim( is_string( $this->last ) ? $this->last : '' ) ) );
53
+ }
54
+
55
+ function is_verified() {
56
+ return ( isset( $this->is_verified ) && true === $this->is_verified );
57
+ }
58
+
59
+ static function get_type() {
60
+ return 'user';
61
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
freemius/languages/freemius-cs_CZ.mo CHANGED
Binary file
freemius/languages/freemius-da_DK.mo CHANGED
Binary file
freemius/languages/freemius-en.mo CHANGED
Binary file
freemius/languages/freemius-es_ES.mo CHANGED
Binary file
freemius/languages/freemius-fr_FR.mo CHANGED
Binary file
freemius/languages/freemius-he_IL.mo CHANGED
Binary file
freemius/languages/freemius-hu_HU.mo CHANGED
Binary file
freemius/languages/freemius-it_IT.mo CHANGED
Binary file
freemius/languages/freemius-ja.mo CHANGED
Binary file
freemius/languages/freemius-nl_NL.mo CHANGED
Binary file
freemius/languages/freemius-ru_RU.mo CHANGED
Binary file
freemius/languages/freemius-ta.mo CHANGED
Binary file
freemius/languages/freemius-zh_CN.mo CHANGED
Binary file
freemius/languages/freemius.pot CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2020 freemius
2
  # This file is distributed under the same license as the freemius package.
3
  msgid ""
4
  msgstr ""
@@ -16,795 +16,795 @@ msgstr ""
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18
 
19
- #: includes/class-freemius.php:1912, templates/account.php:910
20
  msgid "An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned."
21
  msgstr ""
22
 
23
- #: includes/class-freemius.php:1919
24
  msgid "Would you like to proceed with the update?"
25
  msgstr ""
26
 
27
- #: includes/class-freemius.php:2131
28
  msgid "Freemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error."
29
  msgstr ""
30
 
31
- #: includes/class-freemius.php:2133
32
  msgid "Error"
33
  msgstr ""
34
 
35
- #: includes/class-freemius.php:2533
36
  msgid "I found a better %s"
37
  msgstr ""
38
 
39
- #: includes/class-freemius.php:2535
40
  msgid "What's the %s's name?"
41
  msgstr ""
42
 
43
- #: includes/class-freemius.php:2541
44
  msgid "It's a temporary %s. I'm just debugging an issue."
45
  msgstr ""
46
 
47
- #: includes/class-freemius.php:2543
48
  msgid "Deactivation"
49
  msgstr ""
50
 
51
- #: includes/class-freemius.php:2544
52
  msgid "Theme Switch"
53
  msgstr ""
54
 
55
- #: includes/class-freemius.php:2553, templates/forms/resend-key.php:24, templates/forms/user-change.php:29
56
  msgid "Other"
57
  msgstr ""
58
 
59
- #: includes/class-freemius.php:2561
60
  msgid "I no longer need the %s"
61
  msgstr ""
62
 
63
- #: includes/class-freemius.php:2568
64
  msgid "I only needed the %s for a short period"
65
  msgstr ""
66
 
67
- #: includes/class-freemius.php:2574
68
  msgid "The %s broke my site"
69
  msgstr ""
70
 
71
- #: includes/class-freemius.php:2581
72
  msgid "The %s suddenly stopped working"
73
  msgstr ""
74
 
75
- #: includes/class-freemius.php:2591
76
  msgid "I can't pay for it anymore"
77
  msgstr ""
78
 
79
- #: includes/class-freemius.php:2593
80
  msgid "What price would you feel comfortable paying?"
81
  msgstr ""
82
 
83
- #: includes/class-freemius.php:2599
84
  msgid "I don't like to share my information with you"
85
  msgstr ""
86
 
87
- #: includes/class-freemius.php:2620
88
  msgid "The %s didn't work"
89
  msgstr ""
90
 
91
- #: includes/class-freemius.php:2630
92
  msgid "I couldn't understand how to make it work"
93
  msgstr ""
94
 
95
- #: includes/class-freemius.php:2638
96
  msgid "The %s is great, but I need specific feature that you don't support"
97
  msgstr ""
98
 
99
- #: includes/class-freemius.php:2640
100
  msgid "What feature?"
101
  msgstr ""
102
 
103
- #: includes/class-freemius.php:2644
104
  msgid "The %s is not working"
105
  msgstr ""
106
 
107
- #: includes/class-freemius.php:2646
108
  msgid "Kindly share what didn't work so we can fix it for future users..."
109
  msgstr ""
110
 
111
- #: includes/class-freemius.php:2650
112
  msgid "It's not what I was looking for"
113
  msgstr ""
114
 
115
- #: includes/class-freemius.php:2652
116
  msgid "What you've been looking for?"
117
  msgstr ""
118
 
119
- #: includes/class-freemius.php:2656
120
  msgid "The %s didn't work as expected"
121
  msgstr ""
122
 
123
- #: includes/class-freemius.php:2658
124
  msgid "What did you expect?"
125
  msgstr ""
126
 
127
- #: includes/class-freemius.php:3513, templates/debug.php:20
128
  msgid "Freemius Debug"
129
  msgstr ""
130
 
131
- #: includes/class-freemius.php:4265
132
  msgid "I don't know what is cURL or how to install it, help me!"
133
  msgstr ""
134
 
135
- #: includes/class-freemius.php:4267
136
  msgid "We'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update."
137
  msgstr ""
138
 
139
- #: includes/class-freemius.php:4274
140
  msgid "Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again."
141
  msgstr ""
142
 
143
- #: includes/class-freemius.php:4379
144
  msgid "Yes - do your thing"
145
  msgstr ""
146
 
147
- #: includes/class-freemius.php:4384
148
  msgid "No - just deactivate"
149
  msgstr ""
150
 
151
- #: includes/class-freemius.php:4429, includes/class-freemius.php:4923, includes/class-freemius.php:6182, includes/class-freemius.php:13357, includes/class-freemius.php:14075, includes/class-freemius.php:17526, includes/class-freemius.php:17631, includes/class-freemius.php:17806, includes/class-freemius.php:20040, includes/class-freemius.php:20398, includes/class-freemius.php:20408, includes/class-freemius.php:21079, includes/class-freemius.php:21985, includes/class-freemius.php:22118, includes/class-freemius.php:22274, templates/add-ons.php:57
152
  msgctxt "exclamation"
153
  msgid "Oops"
154
  msgstr ""
155
 
156
- #: includes/class-freemius.php:4498
157
  msgid "Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience."
158
  msgstr ""
159
 
160
- #: includes/class-freemius.php:4920
161
  msgctxt "addonX cannot run without pluginY"
162
  msgid "%s cannot run without %s."
163
  msgstr ""
164
 
165
- #: includes/class-freemius.php:4921
166
  msgctxt "addonX cannot run..."
167
  msgid "%s cannot run without the plugin."
168
  msgstr ""
169
 
170
- #: includes/class-freemius.php:5120, includes/class-freemius.php:5145, includes/class-freemius.php:21150
171
  msgid "Unexpected API error. Please contact the %s's author with the following error."
172
  msgstr ""
173
 
174
- #: includes/class-freemius.php:5848
175
  msgid "Premium %s version was successfully activated."
176
  msgstr ""
177
 
178
- #: includes/class-freemius.php:5860, includes/class-freemius.php:7762
179
  msgctxt "Used to express elation, enthusiasm, or triumph (especially in electronic communication)."
180
  msgid "W00t"
181
  msgstr ""
182
 
183
- #: includes/class-freemius.php:5875
184
  msgid "You have a %s license."
185
  msgstr ""
186
 
187
- #: includes/class-freemius.php:5879, includes/class-freemius.php:16925, includes/class-freemius.php:16936, includes/class-freemius.php:20309, includes/class-freemius.php:20659, includes/class-freemius.php:20728, includes/class-freemius.php:20900
188
  msgctxt "interjection expressing joy or exuberance"
189
  msgid "Yee-haw"
190
  msgstr ""
191
 
192
- #: includes/class-freemius.php:6165
193
  msgid "%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license."
194
  msgstr ""
195
 
196
- #: includes/class-freemius.php:6169
197
  msgid "%s is a premium only add-on. You have to purchase a license first before activating the plugin."
198
  msgstr ""
199
 
200
- #: includes/class-freemius.php:6178, templates/add-ons.php:186, templates/account/partials/addon.php:381
201
  msgid "More information about %s"
202
  msgstr ""
203
 
204
- #: includes/class-freemius.php:6179
205
  msgid "Purchase License"
206
  msgstr ""
207
 
208
- #: includes/class-freemius.php:7118, templates/connect.php:171
209
  msgid "You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s."
210
  msgstr ""
211
 
212
- #: includes/class-freemius.php:7122
213
  msgid "start the trial"
214
  msgstr ""
215
 
216
- #: includes/class-freemius.php:7123, templates/connect.php:175
217
  msgid "complete the install"
218
  msgstr ""
219
 
220
- #: includes/class-freemius.php:7241
221
  msgid "You are just one step away - %s"
222
  msgstr ""
223
 
224
- #: includes/class-freemius.php:7244
225
  msgctxt "%s - plugin name. As complete \"PluginX\" activation now"
226
  msgid "Complete \"%s\" Activation Now"
227
  msgstr ""
228
 
229
- #: includes/class-freemius.php:7322
230
  msgid "We made a few tweaks to the %s, %s"
231
  msgstr ""
232
 
233
- #: includes/class-freemius.php:7326
234
  msgid "Opt in to make \"%s\" better!"
235
  msgstr ""
236
 
237
- #: includes/class-freemius.php:7761
238
  msgid "The upgrade of %s was successfully completed."
239
  msgstr ""
240
 
241
- #: includes/class-freemius.php:10243, includes/class-fs-plugin-updater.php:1099, includes/class-fs-plugin-updater.php:1294, includes/class-fs-plugin-updater.php:1301, templates/auto-installation.php:32
242
  msgid "Add-On"
243
  msgstr ""
244
 
245
- #: includes/class-freemius.php:10245, templates/account.php:392, templates/account.php:400, templates/debug.php:358, templates/debug.php:549
246
  msgid "Plugin"
247
  msgstr ""
248
 
249
- #: includes/class-freemius.php:10246, templates/account.php:393, templates/account.php:401, templates/debug.php:358, templates/debug.php:549, templates/forms/deactivation/form.php:71
250
  msgid "Theme"
251
  msgstr ""
252
 
253
- #: includes/class-freemius.php:13176
254
  msgid "An unknown error has occurred while trying to toggle the license's white-label mode."
255
  msgstr ""
256
 
257
- #: includes/class-freemius.php:13190
258
  msgid "Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s."
259
  msgstr ""
260
 
261
- #: includes/class-freemius.php:13195
262
  msgid "User Dashboard"
263
  msgstr ""
264
 
265
- #: includes/class-freemius.php:13196
266
  msgid "revert it now"
267
  msgstr ""
268
 
269
- #: includes/class-freemius.php:13255
270
  msgid "An unknown error has occurred while trying to set the user's beta mode."
271
  msgstr ""
272
 
273
- #: includes/class-freemius.php:13328
274
  msgid "Invalid new user ID or email address."
275
  msgstr ""
276
 
277
- #: includes/class-freemius.php:13358, includes/class-freemius.php:22229
278
  msgid "Sorry, we could not complete the email update. Another user with the same email is already registered."
279
  msgstr ""
280
 
281
- #: includes/class-freemius.php:13359, includes/class-freemius.php:22230
282
  msgid "If you would like to give up the ownership of the %s's account to %s click the Change Ownership button."
283
  msgstr ""
284
 
285
- #: includes/class-freemius.php:13366, includes/class-freemius.php:22237
286
  msgid "Change Ownership"
287
  msgstr ""
288
 
289
- #: includes/class-freemius.php:13942
290
  msgid "Invalid site details collection."
291
  msgstr ""
292
 
293
- #: includes/class-freemius.php:14062
294
  msgid "We couldn't find your email address in the system, are you sure it's the right address?"
295
  msgstr ""
296
 
297
- #: includes/class-freemius.php:14064
298
  msgid "We can't see any active licenses associated with that email address, are you sure it's the right address?"
299
  msgstr ""
300
 
301
- #: includes/class-freemius.php:14338
302
  msgid "Account is pending activation."
303
  msgstr ""
304
 
305
- #: includes/class-freemius.php:14450, templates/forms/premium-versions-upgrade-handler.php:47
306
  msgid "Buy a license now"
307
  msgstr ""
308
 
309
- #: includes/class-freemius.php:14462, templates/forms/premium-versions-upgrade-handler.php:46
310
  msgid "Renew your license now"
311
  msgstr ""
312
 
313
- #: includes/class-freemius.php:14466
314
  msgid "%s to access version %s security & feature updates, and support."
315
  msgstr ""
316
 
317
- #: includes/class-freemius.php:16907
318
  msgid "%s activation was successfully completed."
319
  msgstr ""
320
 
321
- #: includes/class-freemius.php:16921
322
  msgid "Your account was successfully activated with the %s plan."
323
  msgstr ""
324
 
325
- #: includes/class-freemius.php:16932, includes/class-freemius.php:20724
326
  msgid "Your trial has been successfully started."
327
  msgstr ""
328
 
329
- #: includes/class-freemius.php:17524, includes/class-freemius.php:17629, includes/class-freemius.php:17804
330
  msgid "Couldn't activate %s."
331
  msgstr ""
332
 
333
- #: includes/class-freemius.php:17525, includes/class-freemius.php:17630, includes/class-freemius.php:17805
334
  msgid "Please contact us with the following message:"
335
  msgstr ""
336
 
337
- #: includes/class-freemius.php:17626, templates/forms/data-debug-mode.php:162
338
  msgid "An unknown error has occurred."
339
  msgstr ""
340
 
341
- #: includes/class-freemius.php:18162, includes/class-freemius.php:23310
342
  msgid "Upgrade"
343
  msgstr ""
344
 
345
- #: includes/class-freemius.php:18168
346
  msgid "Start Trial"
347
  msgstr ""
348
 
349
- #: includes/class-freemius.php:18170
350
  msgid "Pricing"
351
  msgstr ""
352
 
353
- #: includes/class-freemius.php:18250, includes/class-freemius.php:18252
354
  msgid "Affiliation"
355
  msgstr ""
356
 
357
- #: includes/class-freemius.php:18280, includes/class-freemius.php:18282, templates/account.php:240, templates/debug.php:324
358
  msgid "Account"
359
  msgstr ""
360
 
361
- #: includes/class-freemius.php:18296, includes/class-freemius.php:18298, includes/customizer/class-fs-customizer-support-section.php:60
362
  msgid "Contact Us"
363
  msgstr ""
364
 
365
- #: includes/class-freemius.php:18309, includes/class-freemius.php:18311, includes/class-freemius.php:23324, templates/account.php:119, templates/account/partials/addon.php:44
366
  msgid "Add-Ons"
367
  msgstr ""
368
 
369
- #: includes/class-freemius.php:18345
370
  msgctxt "ASCII arrow left icon"
371
  msgid "&#x2190;"
372
  msgstr ""
373
 
374
- #: includes/class-freemius.php:18345
375
  msgctxt "ASCII arrow right icon"
376
  msgid "&#x27a4;"
377
  msgstr ""
378
 
379
- #: includes/class-freemius.php:18347, templates/pricing.php:109
380
  msgctxt "noun"
381
  msgid "Pricing"
382
  msgstr ""
383
 
384
- #: includes/class-freemius.php:18560, includes/customizer/class-fs-customizer-support-section.php:67
385
  msgid "Support Forum"
386
  msgstr ""
387
 
388
- #: includes/class-freemius.php:19534
389
  msgid "Your email has been successfully verified - you are AWESOME!"
390
  msgstr ""
391
 
392
- #: includes/class-freemius.php:19535
393
  msgctxt "a positive response"
394
  msgid "Right on"
395
  msgstr ""
396
 
397
- #: includes/class-freemius.php:20041
398
  msgid "seems like the key you entered doesn't match our records."
399
  msgstr ""
400
 
401
- #: includes/class-freemius.php:20065
402
  msgid "Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the \"Stop Debug\" link."
403
  msgstr ""
404
 
405
- #: includes/class-freemius.php:20300
406
  msgid "Your %s Add-on plan was successfully upgraded."
407
  msgstr ""
408
 
409
- #: includes/class-freemius.php:20302
410
  msgid "%s Add-on was successfully purchased."
411
  msgstr ""
412
 
413
- #: includes/class-freemius.php:20305
414
  msgid "Download the latest version"
415
  msgstr ""
416
 
417
- #: includes/class-freemius.php:20391
418
  msgid "Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$s"
419
  msgstr ""
420
 
421
- #: includes/class-freemius.php:20397, includes/class-freemius.php:20407, includes/class-freemius.php:20859, includes/class-freemius.php:20948
422
  msgid "Error received from the server:"
423
  msgstr ""
424
 
425
- #: includes/class-freemius.php:20407
426
  msgid "It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again."
427
  msgstr ""
428
 
429
- #: includes/class-freemius.php:20621, includes/class-freemius.php:20864, includes/class-freemius.php:20919, includes/class-freemius.php:21026
430
  msgctxt "something somebody says when they are thinking about what you have just said."
431
  msgid "Hmm"
432
  msgstr ""
433
 
434
- #: includes/class-freemius.php:20634
435
  msgid "It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry."
436
  msgstr ""
437
 
438
- #: includes/class-freemius.php:20635, templates/account.php:121, templates/add-ons.php:250, templates/account/partials/addon.php:46
439
  msgctxt "trial period"
440
  msgid "Trial"
441
  msgstr ""
442
 
443
- #: includes/class-freemius.php:20640
444
  msgid "I have upgraded my account but when I try to Sync the License, the plan remains %s."
445
  msgstr ""
446
 
447
- #: includes/class-freemius.php:20644, includes/class-freemius.php:20703
448
  msgid "Please contact us here"
449
  msgstr ""
450
 
451
- #: includes/class-freemius.php:20655
452
  msgid "Your plan was successfully activated."
453
  msgstr ""
454
 
455
- #: includes/class-freemius.php:20656
456
  msgid "Your plan was successfully upgraded."
457
  msgstr ""
458
 
459
- #: includes/class-freemius.php:20673
460
  msgid "Your plan was successfully changed to %s."
461
  msgstr ""
462
 
463
- #: includes/class-freemius.php:20689
464
  msgid "Your license has expired. You can still continue using the free %s forever."
465
  msgstr ""
466
 
467
- #: includes/class-freemius.php:20691
468
  msgid "Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
469
  msgstr ""
470
 
471
- #: includes/class-freemius.php:20699
472
  msgid "Your license has been cancelled. If you think it's a mistake, please contact support."
473
  msgstr ""
474
 
475
- #: includes/class-freemius.php:20712
476
  msgid "Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support."
477
  msgstr ""
478
 
479
- #: includes/class-freemius.php:20738
480
  msgid "Your free trial has expired. You can still continue using all our free features."
481
  msgstr ""
482
 
483
- #: includes/class-freemius.php:20740
484
  msgid "Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
485
  msgstr ""
486
 
487
- #: includes/class-freemius.php:20855
488
  msgid "It looks like the license could not be activated."
489
  msgstr ""
490
 
491
- #: includes/class-freemius.php:20897
492
  msgid "Your license was successfully activated."
493
  msgstr ""
494
 
495
- #: includes/class-freemius.php:20923
496
  msgid "It looks like your site currently doesn't have an active license."
497
  msgstr ""
498
 
499
- #: includes/class-freemius.php:20947
500
  msgid "It looks like the license deactivation failed."
501
  msgstr ""
502
 
503
- #: includes/class-freemius.php:20976
504
  msgid "Your %s license was successfully deactivated."
505
  msgstr ""
506
 
507
- #: includes/class-freemius.php:20977
508
  msgid "Your license was successfully deactivated, you are back to the %s plan."
509
  msgstr ""
510
 
511
- #: includes/class-freemius.php:20980
512
  msgid "O.K"
513
  msgstr ""
514
 
515
- #: includes/class-freemius.php:21033
516
  msgid "Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes."
517
  msgstr ""
518
 
519
- #: includes/class-freemius.php:21042
520
  msgid "Your subscription was successfully cancelled. Your %s plan license will expire in %s."
521
  msgstr ""
522
 
523
- #: includes/class-freemius.php:21084
524
  msgid "You are already running the %s in a trial mode."
525
  msgstr ""
526
 
527
- #: includes/class-freemius.php:21095
528
  msgid "You already utilized a trial before."
529
  msgstr ""
530
 
531
- #: includes/class-freemius.php:21109
532
  msgid "Plan %s do not exist, therefore, can't start a trial."
533
  msgstr ""
534
 
535
- #: includes/class-freemius.php:21120
536
  msgid "Plan %s does not support a trial period."
537
  msgstr ""
538
 
539
- #: includes/class-freemius.php:21131
540
  msgid "None of the %s's plans supports a trial period."
541
  msgstr ""
542
 
543
- #: includes/class-freemius.php:21181
544
  msgid "It looks like you are not in trial mode anymore so there's nothing to cancel :)"
545
  msgstr ""
546
 
547
- #: includes/class-freemius.php:21217
548
  msgid "Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes."
549
  msgstr ""
550
 
551
- #: includes/class-freemius.php:21236
552
  msgid "Your %s free trial was successfully cancelled."
553
  msgstr ""
554
 
555
- #: includes/class-freemius.php:21552
556
  msgid "Version %s was released."
557
  msgstr ""
558
 
559
- #: includes/class-freemius.php:21552
560
  msgid "Please download %s."
561
  msgstr ""
562
 
563
- #: includes/class-freemius.php:21559
564
  msgid "the latest %s version here"
565
  msgstr ""
566
 
567
- #: includes/class-freemius.php:21564
568
  msgid "New"
569
  msgstr ""
570
 
571
- #: includes/class-freemius.php:21569
572
  msgid "Seems like you got the latest release."
573
  msgstr ""
574
 
575
- #: includes/class-freemius.php:21570
576
  msgid "You are all good!"
577
  msgstr ""
578
 
579
- #: includes/class-freemius.php:21873
580
  msgid "Verification mail was just sent to %s. If you can't find it after 5 min, please check your spam box."
581
  msgstr ""
582
 
583
- #: includes/class-freemius.php:22013
584
  msgid "Site successfully opted in."
585
  msgstr ""
586
 
587
- #: includes/class-freemius.php:22014, includes/class-freemius.php:23020
588
  msgid "Awesome"
589
  msgstr ""
590
 
591
- #: includes/class-freemius.php:22030, templates/forms/optout.php:41
592
  msgid "We appreciate your help in making the %s better by letting us track some usage data."
593
  msgstr ""
594
 
595
- #: includes/class-freemius.php:22031
596
  msgid "Thank you!"
597
  msgstr ""
598
 
599
- #: includes/class-freemius.php:22038
600
  msgid "We will no longer be sending any usage data of %s on %s to %s."
601
  msgstr ""
602
 
603
- #: includes/class-freemius.php:22196
604
  msgid "Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder."
605
  msgstr ""
606
 
607
- #: includes/class-freemius.php:22202
608
  msgid "Thanks for confirming the ownership change. An email was just sent to %s for final approval."
609
  msgstr ""
610
 
611
- #: includes/class-freemius.php:22207
612
  msgid "%s is the new owner of the account."
613
  msgstr ""
614
 
615
- #: includes/class-freemius.php:22209
616
  msgctxt "as congratulations"
617
  msgid "Congrats"
618
  msgstr ""
619
 
620
- #: includes/class-freemius.php:22245
621
  msgid "Your email was successfully updated. You should receive an email with confirmation instructions in few moments."
622
  msgstr ""
623
 
624
- #: includes/class-freemius.php:22257
625
  msgid "Please provide your full name."
626
  msgstr ""
627
 
628
- #: includes/class-freemius.php:22262
629
  msgid "Your name was successfully updated."
630
  msgstr ""
631
 
632
- #: includes/class-freemius.php:22323
633
  msgid "You have successfully updated your %s."
634
  msgstr ""
635
 
636
- #: includes/class-freemius.php:22382
637
  msgid "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin."
638
  msgstr ""
639
 
640
- #: includes/class-freemius.php:22385
641
  msgid "Click here"
642
  msgstr ""
643
 
644
- #: includes/class-freemius.php:22483
645
  msgid "Just letting you know that the add-ons information of %s is being pulled from an external server."
646
  msgstr ""
647
 
648
- #: includes/class-freemius.php:22484
649
  msgctxt "advance notice of something that will need attention."
650
  msgid "Heads up"
651
  msgstr ""
652
 
653
- #: includes/class-freemius.php:23060
654
  msgctxt "exclamation"
655
  msgid "Hey"
656
  msgstr ""
657
 
658
- #: includes/class-freemius.php:23060
659
  msgid "How do you like %s so far? Test all our %s premium features with a %d-day free trial."
660
  msgstr ""
661
 
662
- #: includes/class-freemius.php:23068
663
  msgid "No commitment for %s days - cancel anytime!"
664
  msgstr ""
665
 
666
- #: includes/class-freemius.php:23069
667
  msgid "No credit card required"
668
  msgstr ""
669
 
670
- #: includes/class-freemius.php:23076, templates/forms/trial-start.php:53
671
  msgctxt "call to action"
672
  msgid "Start free trial"
673
  msgstr ""
674
 
675
- #: includes/class-freemius.php:23153
676
  msgid "Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!"
677
  msgstr ""
678
 
679
- #: includes/class-freemius.php:23162
680
  msgid "Learn more"
681
  msgstr ""
682
 
683
- #: includes/class-freemius.php:23348, templates/account.php:556, templates/account.php:706, templates/connect.php:179, templates/connect.php:456, templates/forms/license-activation.php:27, templates/account/partials/addon.php:321
684
  msgid "Activate License"
685
  msgstr ""
686
 
687
- #: includes/class-freemius.php:23349, templates/account.php:650, templates/account.php:705, templates/account/partials/addon.php:322, templates/account/partials/site.php:271
688
  msgid "Change License"
689
  msgstr ""
690
 
691
- #: includes/class-freemius.php:23462, templates/account/partials/site.php:169
692
  msgid "Opt Out"
693
  msgstr ""
694
 
695
- #: includes/class-freemius.php:23464, includes/class-freemius.php:23470, templates/account/partials/site.php:49, templates/account/partials/site.php:169
696
  msgid "Opt In"
697
  msgstr ""
698
 
699
- #: includes/class-freemius.php:23700
700
  msgid " The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"
701
  msgstr ""
702
 
703
- #: includes/class-freemius.php:23708
704
  msgid "Activate %s features"
705
  msgstr ""
706
 
707
- #: includes/class-freemius.php:23721
708
  msgid "Please follow these steps to complete the upgrade"
709
  msgstr ""
710
 
711
- #: includes/class-freemius.php:23725
712
  msgid "Download the latest %s version"
713
  msgstr ""
714
 
715
- #: includes/class-freemius.php:23729
716
  msgid "Upload and activate the downloaded version"
717
  msgstr ""
718
 
719
- #: includes/class-freemius.php:23731
720
  msgid "How to upload and activate?"
721
  msgstr ""
722
 
723
- #: includes/class-freemius.php:23865
724
  msgid "%sClick here%s to choose the sites where you'd like to activate the license on."
725
  msgstr ""
726
 
727
- #: includes/class-freemius.php:24034
728
  msgid "Auto installation only works for opted-in users."
729
  msgstr ""
730
 
731
- #: includes/class-freemius.php:24044, includes/class-freemius.php:24077, includes/class-fs-plugin-updater.php:1273, includes/class-fs-plugin-updater.php:1287
732
  msgid "Invalid module ID."
733
  msgstr ""
734
 
735
- #: includes/class-freemius.php:24053, includes/class-fs-plugin-updater.php:1309
736
  msgid "Premium version already active."
737
  msgstr ""
738
 
739
- #: includes/class-freemius.php:24060
740
  msgid "You do not have a valid license to access the premium version."
741
  msgstr ""
742
 
743
- #: includes/class-freemius.php:24067
744
  msgid "Plugin is a \"Serviceware\" which means it does not have a premium code version."
745
  msgstr ""
746
 
747
- #: includes/class-freemius.php:24085, includes/class-fs-plugin-updater.php:1308
748
  msgid "Premium add-on version already installed."
749
  msgstr ""
750
 
751
- #: includes/class-freemius.php:24435
752
  msgid "View paid features"
753
  msgstr ""
754
 
755
- #: includes/class-freemius.php:24757
756
  msgid "Thank you so much for using %s and its add-ons!"
757
  msgstr ""
758
 
759
- #: includes/class-freemius.php:24758
760
  msgid "Thank you so much for using %s!"
761
  msgstr ""
762
 
763
- #: includes/class-freemius.php:24764
764
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving the %s."
765
  msgstr ""
766
 
767
- #: includes/class-freemius.php:24768
768
  msgid "Thank you so much for using our products!"
769
  msgstr ""
770
 
771
- #: includes/class-freemius.php:24769
772
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving them."
773
  msgstr ""
774
 
775
- #: includes/class-freemius.php:24788
776
  msgid "%s and its add-ons"
777
  msgstr ""
778
 
779
- #: includes/class-freemius.php:24797
780
  msgid "Products"
781
  msgstr ""
782
 
783
- #: includes/class-freemius.php:24804, templates/connect.php:280
784
  msgid "Yes"
785
  msgstr ""
786
 
787
- #: includes/class-freemius.php:24805, templates/connect.php:281
788
  msgid "send me security & feature updates, educational content and offers."
789
  msgstr ""
790
 
791
- #: includes/class-freemius.php:24806, templates/connect.php:286
792
  msgid "No"
793
  msgstr ""
794
 
795
- #: includes/class-freemius.php:24808, templates/connect.php:288
796
  msgid "do %sNOT%s send me security & feature updates, educational content and offers."
797
  msgstr ""
798
 
799
- #: includes/class-freemius.php:24818
800
  msgid "Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)"
801
  msgstr ""
802
 
803
- #: includes/class-freemius.php:24820, templates/connect.php:295
804
  msgid "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:"
805
  msgstr ""
806
 
807
- #: includes/class-freemius.php:25102
808
  msgid "License key is empty."
809
  msgstr ""
810
 
@@ -832,15 +832,15 @@ msgstr ""
832
  msgid "Important Upgrade Notice:"
833
  msgstr ""
834
 
835
- #: includes/class-fs-plugin-updater.php:1338
836
  msgid "Installing plugin: %s"
837
  msgstr ""
838
 
839
- #: includes/class-fs-plugin-updater.php:1379
840
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
841
  msgstr ""
842
 
843
- #: includes/class-fs-plugin-updater.php:1561
844
  msgid "The remote plugin package does not contain a folder with the desired slug and renaming did not work."
845
  msgstr ""
846
 
@@ -861,7 +861,7 @@ msgstr ""
861
  msgid "Install Free Version Update Now"
862
  msgstr ""
863
 
864
- #: includes/fs-plugin-info-dialog.php:745, templates/account.php:639
865
  msgid "Install Update Now"
866
  msgstr ""
867
 
@@ -878,7 +878,7 @@ msgctxt "as download latest version"
878
  msgid "Download Latest Free Version"
879
  msgstr ""
880
 
881
- #: includes/fs-plugin-info-dialog.php:772, templates/account.php:99, templates/add-ons.php:37, templates/account/partials/addon.php:25
882
  msgctxt "as download latest version"
883
  msgid "Download Latest"
884
  msgstr ""
@@ -887,11 +887,11 @@ msgstr ""
887
  msgid "Activate this add-on"
888
  msgstr ""
889
 
890
- #: includes/fs-plugin-info-dialog.php:789, templates/connect.php:453
891
  msgid "Activate Free Version"
892
  msgstr ""
893
 
894
- #: includes/fs-plugin-info-dialog.php:790, templates/account.php:123, templates/add-ons.php:330, templates/account/partials/addon.php:48
895
  msgid "Activate"
896
  msgstr ""
897
 
@@ -1020,7 +1020,7 @@ msgstr ""
1020
  msgid "Details"
1021
  msgstr ""
1022
 
1023
- #: includes/fs-plugin-info-dialog.php:1318, templates/account.php:110, templates/debug.php:201, templates/debug.php:238, templates/debug.php:455, templates/account/partials/addon.php:36
1024
  msgctxt "product version"
1025
  msgid "Version"
1026
  msgstr ""
@@ -1034,7 +1034,7 @@ msgstr ""
1034
  msgid "Last Updated"
1035
  msgstr ""
1036
 
1037
- #: includes/fs-plugin-info-dialog.php:1337, templates/account.php:525
1038
  msgctxt "x-ago"
1039
  msgid "%s ago"
1040
  msgstr ""
@@ -1143,293 +1143,293 @@ msgstr ""
1143
  msgid "Latest Free Version Installed"
1144
  msgstr ""
1145
 
1146
- #: templates/account.php:100, templates/forms/subscription-cancellation.php:96, templates/account/partials/addon.php:26, templates/account/partials/site.php:311
1147
  msgid "Downgrading your plan"
1148
  msgstr ""
1149
 
1150
- #: templates/account.php:101, templates/forms/subscription-cancellation.php:97, templates/account/partials/addon.php:27, templates/account/partials/site.php:312
1151
  msgid "Cancelling the subscription"
1152
  msgstr ""
1153
 
1154
  #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription'
1155
- #: templates/account.php:103, templates/forms/subscription-cancellation.php:99, templates/account/partials/site.php:314
1156
  msgid "%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s."
1157
  msgstr ""
1158
 
1159
- #: templates/account.php:104, templates/forms/subscription-cancellation.php:100, templates/account/partials/addon.php:30, templates/account/partials/site.php:315
1160
  msgid "Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price."
1161
  msgstr ""
1162
 
1163
- #: templates/account.php:105, templates/forms/subscription-cancellation.php:106, templates/account/partials/addon.php:31
1164
  msgid "Cancelling the trial will immediately block access to all premium features. Are you sure?"
1165
  msgstr ""
1166
 
1167
- #: templates/account.php:106, templates/forms/subscription-cancellation.php:101, templates/account/partials/addon.php:32, templates/account/partials/site.php:316
1168
  msgid "You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support."
1169
  msgstr ""
1170
 
1171
- #: templates/account.php:107, templates/forms/subscription-cancellation.php:102, templates/account/partials/addon.php:33, templates/account/partials/site.php:317
1172
  msgid "Once your license expires you can still use the Free version but you will NOT have access to the %s features."
1173
  msgstr ""
1174
 
1175
  #. translators: %s: Plan title (e.g. "Professional")
1176
- #: templates/account.php:109, templates/account/partials/activate-license-button.php:31, templates/account/partials/addon.php:35
1177
  msgid "Activate %s Plan"
1178
  msgstr ""
1179
 
1180
  #. translators: %s: Time period (e.g. Auto renews in "2 months")
1181
- #: templates/account.php:112, templates/account/partials/addon.php:38, templates/account/partials/site.php:291
1182
  msgid "Auto renews in %s"
1183
  msgstr ""
1184
 
1185
  #. translators: %s: Time period (e.g. Expires in "2 months")
1186
- #: templates/account.php:114, templates/account/partials/addon.php:40, templates/account/partials/site.php:293
1187
  msgid "Expires in %s"
1188
  msgstr ""
1189
 
1190
- #: templates/account.php:115
1191
  msgctxt "as synchronize license"
1192
  msgid "Sync License"
1193
  msgstr ""
1194
 
1195
- #: templates/account.php:116, templates/account/partials/addon.php:41
1196
  msgid "Cancel Trial"
1197
  msgstr ""
1198
 
1199
- #: templates/account.php:117, templates/account/partials/addon.php:42
1200
  msgid "Change Plan"
1201
  msgstr ""
1202
 
1203
- #: templates/account.php:118, templates/account/partials/addon.php:43
1204
  msgctxt "verb"
1205
  msgid "Upgrade"
1206
  msgstr ""
1207
 
1208
- #: templates/account.php:120, templates/account/partials/addon.php:45, templates/account/partials/site.php:318
1209
  msgctxt "verb"
1210
  msgid "Downgrade"
1211
  msgstr ""
1212
 
1213
- #: templates/account.php:122, templates/add-ons.php:246, templates/plugin-info/features.php:72, templates/account/partials/addon.php:47, templates/account/partials/site.php:33
1214
  msgid "Free"
1215
  msgstr ""
1216
 
1217
- #: templates/account.php:124, templates/debug.php:371, includes/customizer/class-fs-customizer-upsell-control.php:110, templates/account/partials/addon.php:49
1218
  msgctxt "as product pricing plan"
1219
  msgid "Plan"
1220
  msgstr ""
1221
 
1222
- #: templates/account.php:125
1223
  msgid "Bundle Plan"
1224
  msgstr ""
1225
 
1226
- #: templates/account.php:248
1227
  msgid "Free Trial"
1228
  msgstr ""
1229
 
1230
- #: templates/account.php:259
1231
  msgid "Account Details"
1232
  msgstr ""
1233
 
1234
- #: templates/account.php:266, templates/forms/data-debug-mode.php:33
1235
  msgid "Start Debug"
1236
  msgstr ""
1237
 
1238
- #: templates/account.php:268
1239
  msgid "Stop Debug"
1240
  msgstr ""
1241
 
1242
- #: templates/account.php:275
1243
  msgid "Billing & Invoices"
1244
  msgstr ""
1245
 
1246
- #: templates/account.php:286
1247
  msgid "Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the \"Cancel\" button, and first \"Downgrade\" your account. Are you sure you would like to continue with the deletion?"
1248
  msgstr ""
1249
 
1250
- #: templates/account.php:288
1251
  msgid "Deletion is not temporary. Only delete if you no longer want to use this %s anymore. Are you sure you would like to continue with the deletion?"
1252
  msgstr ""
1253
 
1254
- #: templates/account.php:291
1255
  msgid "Delete Account"
1256
  msgstr ""
1257
 
1258
- #: templates/account.php:303, templates/account/partials/addon.php:231, templates/account/partials/deactivate-license-button.php:35
1259
  msgid "Deactivate License"
1260
  msgstr ""
1261
 
1262
- #: templates/account.php:326, templates/forms/subscription-cancellation.php:125
1263
  msgid "Are you sure you want to proceed?"
1264
  msgstr ""
1265
 
1266
- #: templates/account.php:326, templates/account/partials/addon.php:255
1267
  msgid "Cancel Subscription"
1268
  msgstr ""
1269
 
1270
- #: templates/account.php:355, templates/account/partials/addon.php:340
1271
  msgctxt "as synchronize"
1272
  msgid "Sync"
1273
  msgstr ""
1274
 
1275
- #: templates/account.php:370, templates/debug.php:505
1276
  msgid "Name"
1277
  msgstr ""
1278
 
1279
- #: templates/account.php:376, templates/debug.php:506
1280
  msgid "Email"
1281
  msgstr ""
1282
 
1283
- #: templates/account.php:383, templates/debug.php:369, templates/debug.php:555
1284
  msgid "User ID"
1285
  msgstr ""
1286
 
1287
- #: templates/account.php:401, templates/account.php:719, templates/account.php:752, templates/debug.php:236, templates/debug.php:363, templates/debug.php:452, templates/debug.php:504, templates/debug.php:553, templates/debug.php:632, templates/account/payments.php:35, templates/debug/logger.php:21
1288
  msgid "ID"
1289
  msgstr ""
1290
 
1291
- #: templates/account.php:408
1292
  msgid "Site ID"
1293
  msgstr ""
1294
 
1295
- #: templates/account.php:411
1296
  msgid "No ID"
1297
  msgstr ""
1298
 
1299
- #: templates/account.php:416, templates/debug.php:243, templates/debug.php:372, templates/debug.php:456, templates/debug.php:508, templates/account/partials/site.php:227
1300
  msgid "Public Key"
1301
  msgstr ""
1302
 
1303
- #: templates/account.php:422, templates/debug.php:373, templates/debug.php:457, templates/debug.php:509, templates/account/partials/site.php:239
1304
  msgid "Secret Key"
1305
  msgstr ""
1306
 
1307
- #: templates/account.php:425
1308
  msgctxt "as secret encryption key missing"
1309
  msgid "No Secret"
1310
  msgstr ""
1311
 
1312
- #: templates/account.php:452, templates/account/partials/site.php:120, templates/account/partials/site.php:122
1313
  msgid "Trial"
1314
  msgstr ""
1315
 
1316
- #: templates/account.php:479, templates/debug.php:561, templates/account/partials/site.php:260
1317
  msgid "License Key"
1318
  msgstr ""
1319
 
1320
- #: templates/account.php:510
1321
  msgid "Join the Beta program"
1322
  msgstr ""
1323
 
1324
- #: templates/account.php:516
1325
  msgid "not verified"
1326
  msgstr ""
1327
 
1328
- #: templates/account.php:525, templates/account/partials/addon.php:190
1329
  msgid "Expired"
1330
  msgstr ""
1331
 
1332
- #: templates/account.php:585
1333
  msgid "Premium version"
1334
  msgstr ""
1335
 
1336
- #: templates/account.php:587
1337
  msgid "Free version"
1338
  msgstr ""
1339
 
1340
- #: templates/account.php:599
1341
  msgid "Verify Email"
1342
  msgstr ""
1343
 
1344
- #: templates/account.php:613
1345
  msgid "Download %s Version"
1346
  msgstr ""
1347
 
1348
- #: templates/account.php:629
1349
  msgid "Download Paid Version"
1350
  msgstr ""
1351
 
1352
- #: templates/account.php:647, templates/account.php:890, templates/account/partials/site.php:248, templates/account/partials/site.php:270
1353
  msgctxt "verb"
1354
  msgid "Show"
1355
  msgstr ""
1356
 
1357
- #: templates/account.php:662
1358
  msgid "What is your %s?"
1359
  msgstr ""
1360
 
1361
- #: templates/account.php:670, templates/account/billing.php:21
1362
  msgctxt "verb"
1363
  msgid "Edit"
1364
  msgstr ""
1365
 
1366
- #: templates/account.php:674, templates/forms/user-change.php:27
1367
  msgid "Change User"
1368
  msgstr ""
1369
 
1370
- #: templates/account.php:698
1371
  msgid "Sites"
1372
  msgstr ""
1373
 
1374
- #: templates/account.php:711
1375
  msgid "Search by address"
1376
  msgstr ""
1377
 
1378
- #: templates/account.php:720, templates/debug.php:366
1379
  msgid "Address"
1380
  msgstr ""
1381
 
1382
- #: templates/account.php:721
1383
  msgid "License"
1384
  msgstr ""
1385
 
1386
- #: templates/account.php:722
1387
  msgid "Plan"
1388
  msgstr ""
1389
 
1390
- #: templates/account.php:755
1391
  msgctxt "as software license"
1392
  msgid "License"
1393
  msgstr ""
1394
 
1395
- #: templates/account.php:884
1396
  msgctxt "verb"
1397
  msgid "Hide"
1398
  msgstr ""
1399
 
1400
- #: templates/account.php:906, templates/forms/data-debug-mode.php:31
1401
  msgid "Processing"
1402
  msgstr ""
1403
 
1404
- #: templates/account.php:909
1405
  msgid "Get updates for bleeding edge Beta versions of %s."
1406
  msgstr ""
1407
 
1408
- #: templates/account.php:967
1409
  msgid "Cancelling %s"
1410
  msgstr ""
1411
 
1412
- #: templates/account.php:967, templates/account.php:984, templates/forms/subscription-cancellation.php:27, templates/forms/deactivation/form.php:133
1413
  msgid "trial"
1414
  msgstr ""
1415
 
1416
- #: templates/account.php:982, templates/forms/deactivation/form.php:150
1417
  msgid "Cancelling %s..."
1418
  msgstr ""
1419
 
1420
- #: templates/account.php:985, templates/forms/subscription-cancellation.php:28, templates/forms/deactivation/form.php:134
1421
  msgid "subscription"
1422
  msgstr ""
1423
 
1424
- #: templates/account.php:999
1425
  msgid "Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?"
1426
  msgstr ""
1427
 
1428
- #: templates/account.php:1073
1429
  msgid "Disabling white-label mode"
1430
  msgstr ""
1431
 
1432
- #: templates/account.php:1074
1433
  msgid "Enabling white-label mode"
1434
  msgstr ""
1435
 
@@ -1455,7 +1455,7 @@ msgctxt "installed add-on"
1455
  msgid "Installed"
1456
  msgstr ""
1457
 
1458
- #: templates/admin-notice.php:13, templates/forms/license-activation.php:220, templates/forms/resend-key.php:77
1459
  msgctxt "as close a window"
1460
  msgid "Dismiss"
1461
  msgstr ""
@@ -1510,84 +1510,92 @@ msgstr ""
1510
  msgid "Agree & Activate License"
1511
  msgstr ""
1512
 
1513
- #: templates/connect.php:189
1514
- msgid "Thanks for purchasing %s! To get started, please enter your license key:"
1515
  msgstr ""
1516
 
1517
- #: templates/connect.php:196
1518
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s."
1519
  msgstr ""
1520
 
1521
- #: templates/connect.php:197
1522
  msgid "Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s."
1523
  msgstr ""
1524
 
1525
- #: templates/connect.php:203
1526
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1527
  msgstr ""
1528
 
1529
- #: templates/connect.php:204
1530
  msgid "Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1531
  msgstr ""
1532
 
1533
- #: templates/connect.php:238
1534
  msgid "We're excited to introduce the Freemius network-level integration."
1535
  msgstr ""
1536
 
1537
- #: templates/connect.php:241
1538
  msgid "During the update process we detected %d site(s) that are still pending license activation."
1539
  msgstr ""
1540
 
1541
- #: templates/connect.php:243
1542
  msgid "If you'd like to use the %s on those sites, please enter your license key below and click the activation button."
1543
  msgstr ""
1544
 
1545
- #: templates/connect.php:245
1546
  msgid "%s's paid features"
1547
  msgstr ""
1548
 
1549
- #: templates/connect.php:250
1550
  msgid "Alternatively, you can skip it for now and activate the license later, in your %s's network-level Account page."
1551
  msgstr ""
1552
 
1553
- #: templates/connect.php:252
1554
  msgid "During the update process we detected %s site(s) in the network that are still pending your attention."
1555
  msgstr ""
1556
 
1557
- #: templates/connect.php:261, templates/forms/data-debug-mode.php:35, templates/forms/license-activation.php:49
1558
  msgid "License key"
1559
  msgstr ""
1560
 
1561
- #: templates/connect.php:264, templates/forms/license-activation.php:22
1562
  msgid "Can't find your license key?"
1563
  msgstr ""
1564
 
1565
- #: templates/connect.php:323, templates/connect.php:695, templates/forms/deactivation/retry-skip.php:20
1566
  msgctxt "verb"
1567
  msgid "Skip"
1568
  msgstr ""
1569
 
1570
- #: templates/connect.php:326
1571
  msgid "Delegate to Site Admins"
1572
  msgstr ""
1573
 
1574
- #: templates/connect.php:326
1575
  msgid "If you click it, this decision will be delegated to the sites administrators."
1576
  msgstr ""
1577
 
1578
- #: templates/connect.php:364
 
 
 
 
1579
  msgid "Your Profile Overview"
1580
  msgstr ""
1581
 
1582
- #: templates/connect.php:365
1583
  msgid "Name and email address"
1584
  msgstr ""
1585
 
1586
- #: templates/connect.php:372
 
 
 
 
1587
  msgid "Your Site Overview"
1588
  msgstr ""
1589
 
1590
- #: templates/connect.php:373
1591
  msgid "Site URL, WP version, PHP info"
1592
  msgstr ""
1593
 
@@ -1595,64 +1603,84 @@ msgstr ""
1595
  msgid "Admin Notices"
1596
  msgstr ""
1597
 
1598
- #: templates/connect.php:380, templates/connect.php:396
1599
  msgid "Updates, announcements, marketing, no spam"
1600
  msgstr ""
1601
 
1602
- #: templates/connect.php:386
1603
- msgid "Current %s Events"
 
 
 
 
1604
  msgstr ""
1605
 
1606
- #: templates/connect.php:387
1607
- msgid "Activation, deactivation and uninstall"
1608
  msgstr ""
1609
 
1610
- #: templates/connect.php:395
1611
  msgid "Newsletter"
1612
  msgstr ""
1613
 
1614
- #: templates/connect.php:403
1615
  msgid "Plugins & Themes"
1616
  msgstr ""
1617
 
1618
- #: templates/connect.php:404
 
 
 
 
 
 
 
 
1619
  msgid "Title, slug, version, and is active"
1620
  msgstr ""
1621
 
1622
- #: templates/connect.php:421, templates/forms/license-activation.php:41
1623
- msgid "The %1$s will be periodically sending data to %2$s to check for security and feature updates, and verify the validity of your license."
1624
  msgstr ""
1625
 
1626
  #: templates/connect.php:426
 
 
 
 
 
 
 
 
1627
  msgid "What permissions are being granted?"
1628
  msgstr ""
1629
 
1630
- #: templates/connect.php:452
1631
  msgid "Don't have a license key?"
1632
  msgstr ""
1633
 
1634
- #: templates/connect.php:455
1635
  msgid "Have a license key?"
1636
  msgstr ""
1637
 
1638
- #: templates/connect.php:463
1639
  msgid "Privacy Policy"
1640
  msgstr ""
1641
 
1642
- #: templates/connect.php:465
1643
  msgid "License Agreement"
1644
  msgstr ""
1645
 
1646
- #: templates/connect.php:465
1647
  msgid "Terms of Service"
1648
  msgstr ""
1649
 
1650
- #: templates/connect.php:854
1651
  msgctxt "as in the process of sending an email"
1652
  msgid "Sending email"
1653
  msgstr ""
1654
 
1655
- #: templates/connect.php:855
1656
  msgctxt "as activating plugin"
1657
  msgid "Activating"
1658
  msgstr ""
@@ -2241,7 +2269,11 @@ msgstr ""
2241
  msgid "Update License"
2242
  msgstr ""
2243
 
2244
- #: templates/forms/license-activation.php:181
 
 
 
 
2245
  msgid "Associate with the license owner's account."
2246
  msgstr ""
2247
 
1
+ # Copyright (C) 2021 freemius
2
  # This file is distributed under the same license as the freemius package.
3
  msgid ""
4
  msgstr ""
16
  "X-Poedit-SourceCharset: UTF-8\n"
17
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18
 
19
+ #: includes/class-freemius.php:1919, templates/account.php:912
20
  msgid "An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned."
21
  msgstr ""
22
 
23
+ #: includes/class-freemius.php:1926
24
  msgid "Would you like to proceed with the update?"
25
  msgstr ""
26
 
27
+ #: includes/class-freemius.php:2138
28
  msgid "Freemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error."
29
  msgstr ""
30
 
31
+ #: includes/class-freemius.php:2140
32
  msgid "Error"
33
  msgstr ""
34
 
35
+ #: includes/class-freemius.php:2540
36
  msgid "I found a better %s"
37
  msgstr ""
38
 
39
+ #: includes/class-freemius.php:2542
40
  msgid "What's the %s's name?"
41
  msgstr ""
42
 
43
+ #: includes/class-freemius.php:2548
44
  msgid "It's a temporary %s. I'm just debugging an issue."
45
  msgstr ""
46
 
47
+ #: includes/class-freemius.php:2550
48
  msgid "Deactivation"
49
  msgstr ""
50
 
51
+ #: includes/class-freemius.php:2551
52
  msgid "Theme Switch"
53
  msgstr ""
54
 
55
+ #: includes/class-freemius.php:2560, templates/forms/resend-key.php:24, templates/forms/user-change.php:29
56
  msgid "Other"
57
  msgstr ""
58
 
59
+ #: includes/class-freemius.php:2568
60
  msgid "I no longer need the %s"
61
  msgstr ""
62
 
63
+ #: includes/class-freemius.php:2575
64
  msgid "I only needed the %s for a short period"
65
  msgstr ""
66
 
67
+ #: includes/class-freemius.php:2581
68
  msgid "The %s broke my site"
69
  msgstr ""
70
 
71
+ #: includes/class-freemius.php:2588
72
  msgid "The %s suddenly stopped working"
73
  msgstr ""
74
 
75
+ #: includes/class-freemius.php:2598
76
  msgid "I can't pay for it anymore"
77
  msgstr ""
78
 
79
+ #: includes/class-freemius.php:2600
80
  msgid "What price would you feel comfortable paying?"
81
  msgstr ""
82
 
83
+ #: includes/class-freemius.php:2606
84
  msgid "I don't like to share my information with you"
85
  msgstr ""
86
 
87
+ #: includes/class-freemius.php:2627
88
  msgid "The %s didn't work"
89
  msgstr ""
90
 
91
+ #: includes/class-freemius.php:2637
92
  msgid "I couldn't understand how to make it work"
93
  msgstr ""
94
 
95
+ #: includes/class-freemius.php:2645
96
  msgid "The %s is great, but I need specific feature that you don't support"
97
  msgstr ""
98
 
99
+ #: includes/class-freemius.php:2647
100
  msgid "What feature?"
101
  msgstr ""
102
 
103
+ #: includes/class-freemius.php:2651
104
  msgid "The %s is not working"
105
  msgstr ""
106
 
107
+ #: includes/class-freemius.php:2653
108
  msgid "Kindly share what didn't work so we can fix it for future users..."
109
  msgstr ""
110
 
111
+ #: includes/class-freemius.php:2657
112
  msgid "It's not what I was looking for"
113
  msgstr ""
114
 
115
+ #: includes/class-freemius.php:2659
116
  msgid "What you've been looking for?"
117
  msgstr ""
118
 
119
+ #: includes/class-freemius.php:2663
120
  msgid "The %s didn't work as expected"
121
  msgstr ""
122
 
123
+ #: includes/class-freemius.php:2665
124
  msgid "What did you expect?"
125
  msgstr ""
126
 
127
+ #: includes/class-freemius.php:3520, templates/debug.php:20
128
  msgid "Freemius Debug"
129
  msgstr ""
130
 
131
+ #: includes/class-freemius.php:4272
132
  msgid "I don't know what is cURL or how to install it, help me!"
133
  msgstr ""
134
 
135
+ #: includes/class-freemius.php:4274
136
  msgid "We'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update."
137
  msgstr ""
138
 
139
+ #: includes/class-freemius.php:4281
140
  msgid "Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again."
141
  msgstr ""
142
 
143
+ #: includes/class-freemius.php:4386
144
  msgid "Yes - do your thing"
145
  msgstr ""
146
 
147
+ #: includes/class-freemius.php:4391
148
  msgid "No - just deactivate"
149
  msgstr ""
150
 
151
+ #: includes/class-freemius.php:4436, includes/class-freemius.php:4930, includes/class-freemius.php:6191, includes/class-freemius.php:13368, includes/class-freemius.php:14110, includes/class-freemius.php:17542, includes/class-freemius.php:17647, includes/class-freemius.php:17822, includes/class-freemius.php:20056, includes/class-freemius.php:20414, includes/class-freemius.php:20424, includes/class-freemius.php:21109, includes/class-freemius.php:22015, includes/class-freemius.php:22148, includes/class-freemius.php:22304, templates/add-ons.php:57
152
  msgctxt "exclamation"
153
  msgid "Oops"
154
  msgstr ""
155
 
156
+ #: includes/class-freemius.php:4505
157
  msgid "Thank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience."
158
  msgstr ""
159
 
160
+ #: includes/class-freemius.php:4927
161
  msgctxt "addonX cannot run without pluginY"
162
  msgid "%s cannot run without %s."
163
  msgstr ""
164
 
165
+ #: includes/class-freemius.php:4928
166
  msgctxt "addonX cannot run..."
167
  msgid "%s cannot run without the plugin."
168
  msgstr ""
169
 
170
+ #: includes/class-freemius.php:5127, includes/class-freemius.php:5152, includes/class-freemius.php:21180
171
  msgid "Unexpected API error. Please contact the %s's author with the following error."
172
  msgstr ""
173
 
174
+ #: includes/class-freemius.php:5857
175
  msgid "Premium %s version was successfully activated."
176
  msgstr ""
177
 
178
+ #: includes/class-freemius.php:5869, includes/class-freemius.php:7774
179
  msgctxt "Used to express elation, enthusiasm, or triumph (especially in electronic communication)."
180
  msgid "W00t"
181
  msgstr ""
182
 
183
+ #: includes/class-freemius.php:5884
184
  msgid "You have a %s license."
185
  msgstr ""
186
 
187
+ #: includes/class-freemius.php:5888, includes/class-freemius.php:16947, includes/class-freemius.php:16958, includes/class-freemius.php:20325, includes/class-freemius.php:20689, includes/class-freemius.php:20758, includes/class-freemius.php:20930
188
  msgctxt "interjection expressing joy or exuberance"
189
  msgid "Yee-haw"
190
  msgstr ""
191
 
192
+ #: includes/class-freemius.php:6174
193
  msgid "%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license."
194
  msgstr ""
195
 
196
+ #: includes/class-freemius.php:6178
197
  msgid "%s is a premium only add-on. You have to purchase a license first before activating the plugin."
198
  msgstr ""
199
 
200
+ #: includes/class-freemius.php:6187, templates/add-ons.php:186, templates/account/partials/addon.php:381
201
  msgid "More information about %s"
202
  msgstr ""
203
 
204
+ #: includes/class-freemius.php:6188
205
  msgid "Purchase License"
206
  msgstr ""
207
 
208
+ #: includes/class-freemius.php:7125, templates/connect.php:171
209
  msgid "You should receive an activation email for %s to your mailbox at %s. Please make sure you click the activation button in that email to %s."
210
  msgstr ""
211
 
212
+ #: includes/class-freemius.php:7129
213
  msgid "start the trial"
214
  msgstr ""
215
 
216
+ #: includes/class-freemius.php:7130, templates/connect.php:175
217
  msgid "complete the install"
218
  msgstr ""
219
 
220
+ #: includes/class-freemius.php:7249
221
  msgid "You are just one step away - %s"
222
  msgstr ""
223
 
224
+ #: includes/class-freemius.php:7252
225
  msgctxt "%s - plugin name. As complete \"PluginX\" activation now"
226
  msgid "Complete \"%s\" Activation Now"
227
  msgstr ""
228
 
229
+ #: includes/class-freemius.php:7334
230
  msgid "We made a few tweaks to the %s, %s"
231
  msgstr ""
232
 
233
+ #: includes/class-freemius.php:7338
234
  msgid "Opt in to make \"%s\" better!"
235
  msgstr ""
236
 
237
+ #: includes/class-freemius.php:7773
238
  msgid "The upgrade of %s was successfully completed."
239
  msgstr ""
240
 
241
+ #: includes/class-freemius.php:10255, includes/class-fs-plugin-updater.php:1087, includes/class-fs-plugin-updater.php:1282, includes/class-fs-plugin-updater.php:1289, templates/auto-installation.php:32
242
  msgid "Add-On"
243
  msgstr ""
244
 
245
+ #: includes/class-freemius.php:10257, templates/account.php:394, templates/account.php:402, templates/debug.php:358, templates/debug.php:549
246
  msgid "Plugin"
247
  msgstr ""
248
 
249
+ #: includes/class-freemius.php:10258, templates/account.php:395, templates/account.php:403, templates/debug.php:358, templates/debug.php:549, templates/forms/deactivation/form.php:71
250
  msgid "Theme"
251
  msgstr ""
252
 
253
+ #: includes/class-freemius.php:13188
254
  msgid "An unknown error has occurred while trying to toggle the license's white-label mode."
255
  msgstr ""
256
 
257
+ #: includes/class-freemius.php:13202
258
  msgid "Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s."
259
  msgstr ""
260
 
261
+ #: includes/class-freemius.php:13207
262
  msgid "User Dashboard"
263
  msgstr ""
264
 
265
+ #: includes/class-freemius.php:13208
266
  msgid "revert it now"
267
  msgstr ""
268
 
269
+ #: includes/class-freemius.php:13266
270
  msgid "An unknown error has occurred while trying to set the user's beta mode."
271
  msgstr ""
272
 
273
+ #: includes/class-freemius.php:13339
274
  msgid "Invalid new user ID or email address."
275
  msgstr ""
276
 
277
+ #: includes/class-freemius.php:13369, includes/class-freemius.php:22259
278
  msgid "Sorry, we could not complete the email update. Another user with the same email is already registered."
279
  msgstr ""
280
 
281
+ #: includes/class-freemius.php:13370, includes/class-freemius.php:22260
282
  msgid "If you would like to give up the ownership of the %s's account to %s click the Change Ownership button."
283
  msgstr ""
284
 
285
+ #: includes/class-freemius.php:13377, includes/class-freemius.php:22267
286
  msgid "Change Ownership"
287
  msgstr ""
288
 
289
+ #: includes/class-freemius.php:13977
290
  msgid "Invalid site details collection."
291
  msgstr ""
292
 
293
+ #: includes/class-freemius.php:14097
294
  msgid "We couldn't find your email address in the system, are you sure it's the right address?"
295
  msgstr ""
296
 
297
+ #: includes/class-freemius.php:14099
298
  msgid "We can't see any active licenses associated with that email address, are you sure it's the right address?"
299
  msgstr ""
300
 
301
+ #: includes/class-freemius.php:14373
302
  msgid "Account is pending activation."
303
  msgstr ""
304
 
305
+ #: includes/class-freemius.php:14485, templates/forms/premium-versions-upgrade-handler.php:47
306
  msgid "Buy a license now"
307
  msgstr ""
308
 
309
+ #: includes/class-freemius.php:14497, templates/forms/premium-versions-upgrade-handler.php:46
310
  msgid "Renew your license now"
311
  msgstr ""
312
 
313
+ #: includes/class-freemius.php:14501
314
  msgid "%s to access version %s security & feature updates, and support."
315
  msgstr ""
316
 
317
+ #: includes/class-freemius.php:16929
318
  msgid "%s activation was successfully completed."
319
  msgstr ""
320
 
321
+ #: includes/class-freemius.php:16943
322
  msgid "Your account was successfully activated with the %s plan."
323
  msgstr ""
324
 
325
+ #: includes/class-freemius.php:16954, includes/class-freemius.php:20754
326
  msgid "Your trial has been successfully started."
327
  msgstr ""
328
 
329
+ #: includes/class-freemius.php:17540, includes/class-freemius.php:17645, includes/class-freemius.php:17820
330
  msgid "Couldn't activate %s."
331
  msgstr ""
332
 
333
+ #: includes/class-freemius.php:17541, includes/class-freemius.php:17646, includes/class-freemius.php:17821
334
  msgid "Please contact us with the following message:"
335
  msgstr ""
336
 
337
+ #: includes/class-freemius.php:17642, templates/forms/data-debug-mode.php:162
338
  msgid "An unknown error has occurred."
339
  msgstr ""
340
 
341
+ #: includes/class-freemius.php:18178, includes/class-freemius.php:23340
342
  msgid "Upgrade"
343
  msgstr ""
344
 
345
+ #: includes/class-freemius.php:18184
346
  msgid "Start Trial"
347
  msgstr ""
348
 
349
+ #: includes/class-freemius.php:18186
350
  msgid "Pricing"
351
  msgstr ""
352
 
353
+ #: includes/class-freemius.php:18266, includes/class-freemius.php:18268
354
  msgid "Affiliation"
355
  msgstr ""
356
 
357
+ #: includes/class-freemius.php:18296, includes/class-freemius.php:18298, templates/account.php:242, templates/debug.php:324
358
  msgid "Account"
359
  msgstr ""
360
 
361
+ #: includes/class-freemius.php:18312, includes/class-freemius.php:18314, includes/customizer/class-fs-customizer-support-section.php:60
362
  msgid "Contact Us"
363
  msgstr ""
364
 
365
+ #: includes/class-freemius.php:18325, includes/class-freemius.php:18327, includes/class-freemius.php:23354, templates/account.php:121, templates/account/partials/addon.php:44
366
  msgid "Add-Ons"
367
  msgstr ""
368
 
369
+ #: includes/class-freemius.php:18361
370
  msgctxt "ASCII arrow left icon"
371
  msgid "&#x2190;"
372
  msgstr ""
373
 
374
+ #: includes/class-freemius.php:18361
375
  msgctxt "ASCII arrow right icon"
376
  msgid "&#x27a4;"
377
  msgstr ""
378
 
379
+ #: includes/class-freemius.php:18363, templates/pricing.php:109
380
  msgctxt "noun"
381
  msgid "Pricing"
382
  msgstr ""
383
 
384
+ #: includes/class-freemius.php:18576, includes/customizer/class-fs-customizer-support-section.php:67
385
  msgid "Support Forum"
386
  msgstr ""
387
 
388
+ #: includes/class-freemius.php:19550
389
  msgid "Your email has been successfully verified - you are AWESOME!"
390
  msgstr ""
391
 
392
+ #: includes/class-freemius.php:19551
393
  msgctxt "a positive response"
394
  msgid "Right on"
395
  msgstr ""
396
 
397
+ #: includes/class-freemius.php:20057
398
  msgid "seems like the key you entered doesn't match our records."
399
  msgstr ""
400
 
401
+ #: includes/class-freemius.php:20081
402
  msgid "Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the \"Stop Debug\" link."
403
  msgstr ""
404
 
405
+ #: includes/class-freemius.php:20316
406
  msgid "Your %s Add-on plan was successfully upgraded."
407
  msgstr ""
408
 
409
+ #: includes/class-freemius.php:20318
410
  msgid "%s Add-on was successfully purchased."
411
  msgstr ""
412
 
413
+ #: includes/class-freemius.php:20321
414
  msgid "Download the latest version"
415
  msgstr ""
416
 
417
+ #: includes/class-freemius.php:20407
418
  msgid "Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$s"
419
  msgstr ""
420
 
421
+ #: includes/class-freemius.php:20413, includes/class-freemius.php:20423, includes/class-freemius.php:20889, includes/class-freemius.php:20978
422
  msgid "Error received from the server:"
423
  msgstr ""
424
 
425
+ #: includes/class-freemius.php:20423
426
  msgid "It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again."
427
  msgstr ""
428
 
429
+ #: includes/class-freemius.php:20651, includes/class-freemius.php:20894, includes/class-freemius.php:20949, includes/class-freemius.php:21056
430
  msgctxt "something somebody says when they are thinking about what you have just said."
431
  msgid "Hmm"
432
  msgstr ""
433
 
434
+ #: includes/class-freemius.php:20664
435
  msgid "It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry."
436
  msgstr ""
437
 
438
+ #: includes/class-freemius.php:20665, templates/account.php:123, templates/add-ons.php:250, templates/account/partials/addon.php:46
439
  msgctxt "trial period"
440
  msgid "Trial"
441
  msgstr ""
442
 
443
+ #: includes/class-freemius.php:20670
444
  msgid "I have upgraded my account but when I try to Sync the License, the plan remains %s."
445
  msgstr ""
446
 
447
+ #: includes/class-freemius.php:20674, includes/class-freemius.php:20733
448
  msgid "Please contact us here"
449
  msgstr ""
450
 
451
+ #: includes/class-freemius.php:20685
452
  msgid "Your plan was successfully activated."
453
  msgstr ""
454
 
455
+ #: includes/class-freemius.php:20686
456
  msgid "Your plan was successfully upgraded."
457
  msgstr ""
458
 
459
+ #: includes/class-freemius.php:20703
460
  msgid "Your plan was successfully changed to %s."
461
  msgstr ""
462
 
463
+ #: includes/class-freemius.php:20719
464
  msgid "Your license has expired. You can still continue using the free %s forever."
465
  msgstr ""
466
 
467
+ #: includes/class-freemius.php:20721
468
  msgid "Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
469
  msgstr ""
470
 
471
+ #: includes/class-freemius.php:20729
472
  msgid "Your license has been cancelled. If you think it's a mistake, please contact support."
473
  msgstr ""
474
 
475
+ #: includes/class-freemius.php:20742
476
  msgid "Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support."
477
  msgstr ""
478
 
479
+ #: includes/class-freemius.php:20768
480
  msgid "Your free trial has expired. You can still continue using all our free features."
481
  msgstr ""
482
 
483
+ #: includes/class-freemius.php:20770
484
  msgid "Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions."
485
  msgstr ""
486
 
487
+ #: includes/class-freemius.php:20885
488
  msgid "It looks like the license could not be activated."
489
  msgstr ""
490
 
491
+ #: includes/class-freemius.php:20927
492
  msgid "Your license was successfully activated."
493
  msgstr ""
494
 
495
+ #: includes/class-freemius.php:20953
496
  msgid "It looks like your site currently doesn't have an active license."
497
  msgstr ""
498
 
499
+ #: includes/class-freemius.php:20977
500
  msgid "It looks like the license deactivation failed."
501
  msgstr ""
502
 
503
+ #: includes/class-freemius.php:21006
504
  msgid "Your %s license was successfully deactivated."
505
  msgstr ""
506
 
507
+ #: includes/class-freemius.php:21007
508
  msgid "Your license was successfully deactivated, you are back to the %s plan."
509
  msgstr ""
510
 
511
+ #: includes/class-freemius.php:21010
512
  msgid "O.K"
513
  msgstr ""
514
 
515
+ #: includes/class-freemius.php:21063
516
  msgid "Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes."
517
  msgstr ""
518
 
519
+ #: includes/class-freemius.php:21072
520
  msgid "Your subscription was successfully cancelled. Your %s plan license will expire in %s."
521
  msgstr ""
522
 
523
+ #: includes/class-freemius.php:21114
524
  msgid "You are already running the %s in a trial mode."
525
  msgstr ""
526
 
527
+ #: includes/class-freemius.php:21125
528
  msgid "You already utilized a trial before."
529
  msgstr ""
530
 
531
+ #: includes/class-freemius.php:21139
532
  msgid "Plan %s do not exist, therefore, can't start a trial."
533
  msgstr ""
534
 
535
+ #: includes/class-freemius.php:21150
536
  msgid "Plan %s does not support a trial period."
537
  msgstr ""
538
 
539
+ #: includes/class-freemius.php:21161
540
  msgid "None of the %s's plans supports a trial period."
541
  msgstr ""
542
 
543
+ #: includes/class-freemius.php:21211
544
  msgid "It looks like you are not in trial mode anymore so there's nothing to cancel :)"
545
  msgstr ""
546
 
547
+ #: includes/class-freemius.php:21247
548
  msgid "Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes."
549
  msgstr ""
550
 
551
+ #: includes/class-freemius.php:21266
552
  msgid "Your %s free trial was successfully cancelled."
553
  msgstr ""
554
 
555
+ #: includes/class-freemius.php:21582
556
  msgid "Version %s was released."
557
  msgstr ""
558
 
559
+ #: includes/class-freemius.php:21582
560
  msgid "Please download %s."
561
  msgstr ""
562
 
563
+ #: includes/class-freemius.php:21589
564
  msgid "the latest %s version here"
565
  msgstr ""
566
 
567
+ #: includes/class-freemius.php:21594
568
  msgid "New"
569
  msgstr ""
570
 
571
+ #: includes/class-freemius.php:21599
572
  msgid "Seems like you got the latest release."
573
  msgstr ""
574
 
575
+ #: includes/class-freemius.php:21600
576
  msgid "You are all good!"
577
  msgstr ""
578
 
579
+ #: includes/class-freemius.php:21903
580
  msgid "Verification mail was just sent to %s. If you can't find it after 5 min, please check your spam box."
581
  msgstr ""
582
 
583
+ #: includes/class-freemius.php:22043
584
  msgid "Site successfully opted in."
585
  msgstr ""
586
 
587
+ #: includes/class-freemius.php:22044, includes/class-freemius.php:23050
588
  msgid "Awesome"
589
  msgstr ""
590
 
591
+ #: includes/class-freemius.php:22060, templates/forms/optout.php:41
592
  msgid "We appreciate your help in making the %s better by letting us track some usage data."
593
  msgstr ""
594
 
595
+ #: includes/class-freemius.php:22061
596
  msgid "Thank you!"
597
  msgstr ""
598
 
599
+ #: includes/class-freemius.php:22068
600
  msgid "We will no longer be sending any usage data of %s on %s to %s."
601
  msgstr ""
602
 
603
+ #: includes/class-freemius.php:22226
604
  msgid "Please check your mailbox, you should receive an email via %s to confirm the ownership change. From security reasons, you must confirm the change within the next 15 min. If you cannot find the email, please check your spam folder."
605
  msgstr ""
606
 
607
+ #: includes/class-freemius.php:22232
608
  msgid "Thanks for confirming the ownership change. An email was just sent to %s for final approval."
609
  msgstr ""
610
 
611
+ #: includes/class-freemius.php:22237
612
  msgid "%s is the new owner of the account."
613
  msgstr ""
614
 
615
+ #: includes/class-freemius.php:22239
616
  msgctxt "as congratulations"
617
  msgid "Congrats"
618
  msgstr ""
619
 
620
+ #: includes/class-freemius.php:22275
621
  msgid "Your email was successfully updated. You should receive an email with confirmation instructions in few moments."
622
  msgstr ""
623
 
624
+ #: includes/class-freemius.php:22287
625
  msgid "Please provide your full name."
626
  msgstr ""
627
 
628
+ #: includes/class-freemius.php:22292
629
  msgid "Your name was successfully updated."
630
  msgstr ""
631
 
632
+ #: includes/class-freemius.php:22353
633
  msgid "You have successfully updated your %s."
634
  msgstr ""
635
 
636
+ #: includes/class-freemius.php:22412
637
  msgid "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin."
638
  msgstr ""
639
 
640
+ #: includes/class-freemius.php:22415
641
  msgid "Click here"
642
  msgstr ""
643
 
644
+ #: includes/class-freemius.php:22513
645
  msgid "Just letting you know that the add-ons information of %s is being pulled from an external server."
646
  msgstr ""
647
 
648
+ #: includes/class-freemius.php:22514
649
  msgctxt "advance notice of something that will need attention."
650
  msgid "Heads up"
651
  msgstr ""
652
 
653
+ #: includes/class-freemius.php:23090
654
  msgctxt "exclamation"
655
  msgid "Hey"
656
  msgstr ""
657
 
658
+ #: includes/class-freemius.php:23090
659
  msgid "How do you like %s so far? Test all our %s premium features with a %d-day free trial."
660
  msgstr ""
661
 
662
+ #: includes/class-freemius.php:23098
663
  msgid "No commitment for %s days - cancel anytime!"
664
  msgstr ""
665
 
666
+ #: includes/class-freemius.php:23099
667
  msgid "No credit card required"
668
  msgstr ""
669
 
670
+ #: includes/class-freemius.php:23106, templates/forms/trial-start.php:53
671
  msgctxt "call to action"
672
  msgid "Start free trial"
673
  msgstr ""
674
 
675
+ #: includes/class-freemius.php:23183
676
  msgid "Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!"
677
  msgstr ""
678
 
679
+ #: includes/class-freemius.php:23192
680
  msgid "Learn more"
681
  msgstr ""
682
 
683
+ #: includes/class-freemius.php:23378, templates/account.php:558, templates/account.php:708, templates/connect.php:179, templates/connect.php:461, templates/forms/license-activation.php:27, templates/account/partials/addon.php:321
684
  msgid "Activate License"
685
  msgstr ""
686
 
687
+ #: includes/class-freemius.php:23379, templates/account.php:652, templates/account.php:707, templates/account/partials/addon.php:322, templates/account/partials/site.php:271
688
  msgid "Change License"
689
  msgstr ""
690
 
691
+ #: includes/class-freemius.php:23500, templates/account/partials/site.php:169
692
  msgid "Opt Out"
693
  msgstr ""
694
 
695
+ #: includes/class-freemius.php:23502, includes/class-freemius.php:23508, templates/account/partials/site.php:49, templates/account/partials/site.php:169
696
  msgid "Opt In"
697
  msgstr ""
698
 
699
+ #: includes/class-freemius.php:23738
700
  msgid " The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"
701
  msgstr ""
702
 
703
+ #: includes/class-freemius.php:23746
704
  msgid "Activate %s features"
705
  msgstr ""
706
 
707
+ #: includes/class-freemius.php:23759
708
  msgid "Please follow these steps to complete the upgrade"
709
  msgstr ""
710
 
711
+ #: includes/class-freemius.php:23763
712
  msgid "Download the latest %s version"
713
  msgstr ""
714
 
715
+ #: includes/class-freemius.php:23767
716
  msgid "Upload and activate the downloaded version"
717
  msgstr ""
718
 
719
+ #: includes/class-freemius.php:23769
720
  msgid "How to upload and activate?"
721
  msgstr ""
722
 
723
+ #: includes/class-freemius.php:23903
724
  msgid "%sClick here%s to choose the sites where you'd like to activate the license on."
725
  msgstr ""
726
 
727
+ #: includes/class-freemius.php:24072
728
  msgid "Auto installation only works for opted-in users."
729
  msgstr ""
730
 
731
+ #: includes/class-freemius.php:24082, includes/class-freemius.php:24115, includes/class-fs-plugin-updater.php:1261, includes/class-fs-plugin-updater.php:1275
732
  msgid "Invalid module ID."
733
  msgstr ""
734
 
735
+ #: includes/class-freemius.php:24091, includes/class-fs-plugin-updater.php:1297
736
  msgid "Premium version already active."
737
  msgstr ""
738
 
739
+ #: includes/class-freemius.php:24098
740
  msgid "You do not have a valid license to access the premium version."
741
  msgstr ""
742
 
743
+ #: includes/class-freemius.php:24105
744
  msgid "Plugin is a \"Serviceware\" which means it does not have a premium code version."
745
  msgstr ""
746
 
747
+ #: includes/class-freemius.php:24123, includes/class-fs-plugin-updater.php:1296
748
  msgid "Premium add-on version already installed."
749
  msgstr ""
750
 
751
+ #: includes/class-freemius.php:24473
752
  msgid "View paid features"
753
  msgstr ""
754
 
755
+ #: includes/class-freemius.php:24795
756
  msgid "Thank you so much for using %s and its add-ons!"
757
  msgstr ""
758
 
759
+ #: includes/class-freemius.php:24796
760
  msgid "Thank you so much for using %s!"
761
  msgstr ""
762
 
763
+ #: includes/class-freemius.php:24802
764
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving the %s."
765
  msgstr ""
766
 
767
+ #: includes/class-freemius.php:24806
768
  msgid "Thank you so much for using our products!"
769
  msgstr ""
770
 
771
+ #: includes/class-freemius.php:24807
772
  msgid "You've already opted-in to our usage-tracking, which helps us keep improving them."
773
  msgstr ""
774
 
775
+ #: includes/class-freemius.php:24826
776
  msgid "%s and its add-ons"
777
  msgstr ""
778
 
779
+ #: includes/class-freemius.php:24835
780
  msgid "Products"
781
  msgstr ""
782
 
783
+ #: includes/class-freemius.php:24842, templates/connect.php:275
784
  msgid "Yes"
785
  msgstr ""
786
 
787
+ #: includes/class-freemius.php:24843, templates/connect.php:276
788
  msgid "send me security & feature updates, educational content and offers."
789
  msgstr ""
790
 
791
+ #: includes/class-freemius.php:24844, templates/connect.php:281
792
  msgid "No"
793
  msgstr ""
794
 
795
+ #: includes/class-freemius.php:24846, templates/connect.php:283
796
  msgid "do %sNOT%s send me security & feature updates, educational content and offers."
797
  msgstr ""
798
 
799
+ #: includes/class-freemius.php:24856
800
  msgid "Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)"
801
  msgstr ""
802
 
803
+ #: includes/class-freemius.php:24858, templates/connect.php:290
804
  msgid "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:"
805
  msgstr ""
806
 
807
+ #: includes/class-freemius.php:25140
808
  msgid "License key is empty."
809
  msgstr ""
810
 
832
  msgid "Important Upgrade Notice:"
833
  msgstr ""
834
 
835
+ #: includes/class-fs-plugin-updater.php:1326
836
  msgid "Installing plugin: %s"
837
  msgstr ""
838
 
839
+ #: includes/class-fs-plugin-updater.php:1367
840
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
841
  msgstr ""
842
 
843
+ #: includes/class-fs-plugin-updater.php:1549
844
  msgid "The remote plugin package does not contain a folder with the desired slug and renaming did not work."
845
  msgstr ""
846
 
861
  msgid "Install Free Version Update Now"
862
  msgstr ""
863
 
864
+ #: includes/fs-plugin-info-dialog.php:745, templates/account.php:641
865
  msgid "Install Update Now"
866
  msgstr ""
867
 
878
  msgid "Download Latest Free Version"
879
  msgstr ""
880
 
881
+ #: includes/fs-plugin-info-dialog.php:772, templates/account.php:101, templates/add-ons.php:37, templates/account/partials/addon.php:25
882
  msgctxt "as download latest version"
883
  msgid "Download Latest"
884
  msgstr ""
887
  msgid "Activate this add-on"
888
  msgstr ""
889
 
890
+ #: includes/fs-plugin-info-dialog.php:789, templates/connect.php:458
891
  msgid "Activate Free Version"
892
  msgstr ""
893
 
894
+ #: includes/fs-plugin-info-dialog.php:790, templates/account.php:125, templates/add-ons.php:330, templates/account/partials/addon.php:48
895
  msgid "Activate"
896
  msgstr ""
897
 
1020
  msgid "Details"
1021
  msgstr ""
1022
 
1023
+ #: includes/fs-plugin-info-dialog.php:1318, templates/account.php:112, templates/debug.php:201, templates/debug.php:238, templates/debug.php:455, templates/account/partials/addon.php:36
1024
  msgctxt "product version"
1025
  msgid "Version"
1026
  msgstr ""
1034
  msgid "Last Updated"
1035
  msgstr ""
1036
 
1037
+ #: includes/fs-plugin-info-dialog.php:1337, templates/account.php:527
1038
  msgctxt "x-ago"
1039
  msgid "%s ago"
1040
  msgstr ""
1143
  msgid "Latest Free Version Installed"
1144
  msgstr ""
1145
 
1146
+ #: templates/account.php:102, templates/forms/subscription-cancellation.php:96, templates/account/partials/addon.php:26, templates/account/partials/site.php:311
1147
  msgid "Downgrading your plan"
1148
  msgstr ""
1149
 
1150
+ #: templates/account.php:103, templates/forms/subscription-cancellation.php:97, templates/account/partials/addon.php:27, templates/account/partials/site.php:312
1151
  msgid "Cancelling the subscription"
1152
  msgstr ""
1153
 
1154
  #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription'
1155
+ #: templates/account.php:105, templates/forms/subscription-cancellation.php:99, templates/account/partials/site.php:314
1156
  msgid "%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s."
1157
  msgstr ""
1158
 
1159
+ #: templates/account.php:106, templates/forms/subscription-cancellation.php:100, templates/account/partials/addon.php:30, templates/account/partials/site.php:315
1160
  msgid "Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price."
1161
  msgstr ""
1162
 
1163
+ #: templates/account.php:107, templates/forms/subscription-cancellation.php:106, templates/account/partials/addon.php:31
1164
  msgid "Cancelling the trial will immediately block access to all premium features. Are you sure?"
1165
  msgstr ""
1166
 
1167
+ #: templates/account.php:108, templates/forms/subscription-cancellation.php:101, templates/account/partials/addon.php:32, templates/account/partials/site.php:316
1168
  msgid "You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support."
1169
  msgstr ""
1170
 
1171
+ #: templates/account.php:109, templates/forms/subscription-cancellation.php:102, templates/account/partials/addon.php:33, templates/account/partials/site.php:317
1172
  msgid "Once your license expires you can still use the Free version but you will NOT have access to the %s features."
1173
  msgstr ""
1174
 
1175
  #. translators: %s: Plan title (e.g. "Professional")
1176
+ #: templates/account.php:111, templates/account/partials/activate-license-button.php:31, templates/account/partials/addon.php:35
1177
  msgid "Activate %s Plan"
1178
  msgstr ""
1179
 
1180
  #. translators: %s: Time period (e.g. Auto renews in "2 months")
1181
+ #: templates/account.php:114, templates/account/partials/addon.php:38, templates/account/partials/site.php:291
1182
  msgid "Auto renews in %s"
1183
  msgstr ""
1184
 
1185
  #. translators: %s: Time period (e.g. Expires in "2 months")
1186
+ #: templates/account.php:116, templates/account/partials/addon.php:40, templates/account/partials/site.php:293
1187
  msgid "Expires in %s"
1188
  msgstr ""
1189
 
1190
+ #: templates/account.php:117
1191
  msgctxt "as synchronize license"
1192
  msgid "Sync License"
1193
  msgstr ""
1194
 
1195
+ #: templates/account.php:118, templates/account/partials/addon.php:41
1196
  msgid "Cancel Trial"
1197
  msgstr ""
1198
 
1199
+ #: templates/account.php:119, templates/account/partials/addon.php:42
1200
  msgid "Change Plan"
1201
  msgstr ""
1202
 
1203
+ #: templates/account.php:120, templates/account/partials/addon.php:43
1204
  msgctxt "verb"
1205
  msgid "Upgrade"
1206
  msgstr ""
1207
 
1208
+ #: templates/account.php:122, templates/account/partials/addon.php:45, templates/account/partials/site.php:318
1209
  msgctxt "verb"
1210
  msgid "Downgrade"
1211
  msgstr ""
1212
 
1213
+ #: templates/account.php:124, templates/add-ons.php:246, templates/plugin-info/features.php:72, templates/account/partials/addon.php:47, templates/account/partials/site.php:33
1214
  msgid "Free"
1215
  msgstr ""
1216
 
1217
+ #: templates/account.php:126, templates/debug.php:371, includes/customizer/class-fs-customizer-upsell-control.php:110, templates/account/partials/addon.php:49
1218
  msgctxt "as product pricing plan"
1219
  msgid "Plan"
1220
  msgstr ""
1221
 
1222
+ #: templates/account.php:127
1223
  msgid "Bundle Plan"
1224
  msgstr ""
1225
 
1226
+ #: templates/account.php:250
1227
  msgid "Free Trial"
1228
  msgstr ""
1229
 
1230
+ #: templates/account.php:261
1231
  msgid "Account Details"
1232
  msgstr ""
1233
 
1234
+ #: templates/account.php:268, templates/forms/data-debug-mode.php:33
1235
  msgid "Start Debug"
1236
  msgstr ""
1237
 
1238
+ #: templates/account.php:270
1239
  msgid "Stop Debug"
1240
  msgstr ""
1241
 
1242
+ #: templates/account.php:277
1243
  msgid "Billing & Invoices"
1244
  msgstr ""
1245
 
1246
+ #: templates/account.php:288
1247
  msgid "Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the \"Cancel\" button, and first \"Downgrade\" your account. Are you sure you would like to continue with the deletion?"
1248
  msgstr ""
1249
 
1250
+ #: templates/account.php:290
1251
  msgid "Deletion is not temporary. Only delete if you no longer want to use this %s anymore. Are you sure you would like to continue with the deletion?"
1252
  msgstr ""
1253
 
1254
+ #: templates/account.php:293
1255
  msgid "Delete Account"
1256
  msgstr ""
1257
 
1258
+ #: templates/account.php:305, templates/account/partials/addon.php:231, templates/account/partials/deactivate-license-button.php:35
1259
  msgid "Deactivate License"
1260
  msgstr ""
1261
 
1262
+ #: templates/account.php:328, templates/forms/subscription-cancellation.php:125
1263
  msgid "Are you sure you want to proceed?"
1264
  msgstr ""
1265
 
1266
+ #: templates/account.php:328, templates/account/partials/addon.php:255
1267
  msgid "Cancel Subscription"
1268
  msgstr ""
1269
 
1270
+ #: templates/account.php:357, templates/account/partials/addon.php:340
1271
  msgctxt "as synchronize"
1272
  msgid "Sync"
1273
  msgstr ""
1274
 
1275
+ #: templates/account.php:372, templates/debug.php:505
1276
  msgid "Name"
1277
  msgstr ""
1278
 
1279
+ #: templates/account.php:378, templates/debug.php:506
1280
  msgid "Email"
1281
  msgstr ""
1282
 
1283
+ #: templates/account.php:385, templates/debug.php:369, templates/debug.php:555
1284
  msgid "User ID"
1285
  msgstr ""
1286
 
1287
+ #: templates/account.php:403, templates/account.php:721, templates/account.php:754, templates/debug.php:236, templates/debug.php:363, templates/debug.php:452, templates/debug.php:504, templates/debug.php:553, templates/debug.php:632, templates/account/payments.php:35, templates/debug/logger.php:21
1288
  msgid "ID"
1289
  msgstr ""
1290
 
1291
+ #: templates/account.php:410
1292
  msgid "Site ID"
1293
  msgstr ""
1294
 
1295
+ #: templates/account.php:413
1296
  msgid "No ID"
1297
  msgstr ""
1298
 
1299
+ #: templates/account.php:418, templates/debug.php:243, templates/debug.php:372, templates/debug.php:456, templates/debug.php:508, templates/account/partials/site.php:227
1300
  msgid "Public Key"
1301
  msgstr ""
1302
 
1303
+ #: templates/account.php:424, templates/debug.php:373, templates/debug.php:457, templates/debug.php:509, templates/account/partials/site.php:239
1304
  msgid "Secret Key"
1305
  msgstr ""
1306
 
1307
+ #: templates/account.php:427
1308
  msgctxt "as secret encryption key missing"
1309
  msgid "No Secret"
1310
  msgstr ""
1311
 
1312
+ #: templates/account.php:454, templates/account/partials/site.php:120, templates/account/partials/site.php:122
1313
  msgid "Trial"
1314
  msgstr ""
1315
 
1316
+ #: templates/account.php:481, templates/debug.php:561, templates/account/partials/site.php:260
1317
  msgid "License Key"
1318
  msgstr ""
1319
 
1320
+ #: templates/account.php:512
1321
  msgid "Join the Beta program"
1322
  msgstr ""
1323
 
1324
+ #: templates/account.php:518
1325
  msgid "not verified"
1326
  msgstr ""
1327
 
1328
+ #: templates/account.php:527, templates/account/partials/addon.php:190
1329
  msgid "Expired"
1330
  msgstr ""
1331
 
1332
+ #: templates/account.php:587
1333
  msgid "Premium version"
1334
  msgstr ""
1335
 
1336
+ #: templates/account.php:589
1337
  msgid "Free version"
1338
  msgstr ""
1339
 
1340
+ #: templates/account.php:601
1341
  msgid "Verify Email"
1342
  msgstr ""
1343
 
1344
+ #: templates/account.php:615
1345
  msgid "Download %s Version"
1346
  msgstr ""
1347
 
1348
+ #: templates/account.php:631
1349
  msgid "Download Paid Version"
1350
  msgstr ""
1351
 
1352
+ #: templates/account.php:649, templates/account.php:892, templates/account/partials/site.php:248, templates/account/partials/site.php:270
1353
  msgctxt "verb"
1354
  msgid "Show"
1355
  msgstr ""
1356
 
1357
+ #: templates/account.php:664
1358
  msgid "What is your %s?"
1359
  msgstr ""
1360
 
1361
+ #: templates/account.php:672, templates/account/billing.php:21
1362
  msgctxt "verb"
1363
  msgid "Edit"
1364
  msgstr ""
1365
 
1366
+ #: templates/account.php:676, templates/forms/user-change.php:27
1367
  msgid "Change User"
1368
  msgstr ""
1369
 
1370
+ #: templates/account.php:700
1371
  msgid "Sites"
1372
  msgstr ""
1373
 
1374
+ #: templates/account.php:713
1375
  msgid "Search by address"
1376
  msgstr ""
1377
 
1378
+ #: templates/account.php:722, templates/debug.php:366
1379
  msgid "Address"
1380
  msgstr ""
1381
 
1382
+ #: templates/account.php:723
1383
  msgid "License"
1384
  msgstr ""
1385
 
1386
+ #: templates/account.php:724
1387
  msgid "Plan"
1388
  msgstr ""
1389
 
1390
+ #: templates/account.php:757
1391
  msgctxt "as software license"
1392
  msgid "License"
1393
  msgstr ""
1394
 
1395
+ #: templates/account.php:886
1396
  msgctxt "verb"
1397
  msgid "Hide"
1398
  msgstr ""
1399
 
1400
+ #: templates/account.php:908, templates/forms/data-debug-mode.php:31
1401
  msgid "Processing"
1402
  msgstr ""
1403
 
1404
+ #: templates/account.php:911
1405
  msgid "Get updates for bleeding edge Beta versions of %s."
1406
  msgstr ""
1407
 
1408
+ #: templates/account.php:969
1409
  msgid "Cancelling %s"
1410
  msgstr ""
1411
 
1412
+ #: templates/account.php:969, templates/account.php:986, templates/forms/subscription-cancellation.php:27, templates/forms/deactivation/form.php:133
1413
  msgid "trial"
1414
  msgstr ""
1415
 
1416
+ #: templates/account.php:984, templates/forms/deactivation/form.php:150
1417
  msgid "Cancelling %s..."
1418
  msgstr ""
1419
 
1420
+ #: templates/account.php:987, templates/forms/subscription-cancellation.php:28, templates/forms/deactivation/form.php:134
1421
  msgid "subscription"
1422
  msgstr ""
1423
 
1424
+ #: templates/account.php:1001
1425
  msgid "Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?"
1426
  msgstr ""
1427
 
1428
+ #: templates/account.php:1075
1429
  msgid "Disabling white-label mode"
1430
  msgstr ""
1431
 
1432
+ #: templates/account.php:1076
1433
  msgid "Enabling white-label mode"
1434
  msgstr ""
1435
 
1455
  msgid "Installed"
1456
  msgstr ""
1457
 
1458
+ #: templates/admin-notice.php:13, templates/forms/license-activation.php:222, templates/forms/resend-key.php:77
1459
  msgctxt "as close a window"
1460
  msgid "Dismiss"
1461
  msgstr ""
1510
  msgid "Agree & Activate License"
1511
  msgstr ""
1512
 
1513
+ #: templates/connect.php:184
1514
+ msgid "Welcome to %s! To get started, please enter your license key:"
1515
  msgstr ""
1516
 
1517
+ #: templates/connect.php:191
1518
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s."
1519
  msgstr ""
1520
 
1521
+ #: templates/connect.php:192
1522
  msgid "Never miss an important update - opt in to our security and feature updates notifications, and non-sensitive diagnostic tracking with %4$s."
1523
  msgstr ""
1524
 
1525
+ #: templates/connect.php:198
1526
  msgid "Never miss an important update - opt in to our security & feature updates notifications, educational content, offers, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1527
  msgstr ""
1528
 
1529
+ #: templates/connect.php:199
1530
  msgid "Never miss an important update - opt in to our security & feature updates notifications, and non-sensitive diagnostic tracking with %4$s. If you skip this, that's okay! %1$s will still work just fine."
1531
  msgstr ""
1532
 
1533
+ #: templates/connect.php:233
1534
  msgid "We're excited to introduce the Freemius network-level integration."
1535
  msgstr ""
1536
 
1537
+ #: templates/connect.php:236
1538
  msgid "During the update process we detected %d site(s) that are still pending license activation."
1539
  msgstr ""
1540
 
1541
+ #: templates/connect.php:238
1542
  msgid "If you'd like to use the %s on those sites, please enter your license key below and click the activation button."
1543
  msgstr ""
1544
 
1545
+ #: templates/connect.php:240
1546
  msgid "%s's paid features"
1547
  msgstr ""
1548
 
1549
+ #: templates/connect.php:245
1550
  msgid "Alternatively, you can skip it for now and activate the license later, in your %s's network-level Account page."
1551
  msgstr ""
1552
 
1553
+ #: templates/connect.php:247
1554
  msgid "During the update process we detected %s site(s) in the network that are still pending your attention."
1555
  msgstr ""
1556
 
1557
+ #: templates/connect.php:256, templates/forms/data-debug-mode.php:35, templates/forms/license-activation.php:49
1558
  msgid "License key"
1559
  msgstr ""
1560
 
1561
+ #: templates/connect.php:259, templates/forms/license-activation.php:22
1562
  msgid "Can't find your license key?"
1563
  msgstr ""
1564
 
1565
+ #: templates/connect.php:318, templates/connect.php:700, templates/forms/deactivation/retry-skip.php:20
1566
  msgctxt "verb"
1567
  msgid "Skip"
1568
  msgstr ""
1569
 
1570
+ #: templates/connect.php:321
1571
  msgid "Delegate to Site Admins"
1572
  msgstr ""
1573
 
1574
+ #: templates/connect.php:321
1575
  msgid "If you click it, this decision will be delegated to the sites administrators."
1576
  msgstr ""
1577
 
1578
+ #: templates/connect.php:346
1579
+ msgid "License issues?"
1580
+ msgstr ""
1581
+
1582
+ #: templates/connect.php:362
1583
  msgid "Your Profile Overview"
1584
  msgstr ""
1585
 
1586
+ #: templates/connect.php:363
1587
  msgid "Name and email address"
1588
  msgstr ""
1589
 
1590
+ #: templates/connect.php:370
1591
+ msgid "So you can manage and control your license remotely from the User Dashboard."
1592
+ msgstr ""
1593
+
1594
+ #: templates/connect.php:371
1595
  msgid "Your Site Overview"
1596
  msgstr ""
1597
 
1598
+ #: templates/connect.php:372
1599
  msgid "Site URL, WP version, PHP info"
1600
  msgstr ""
1601
 
1603
  msgid "Admin Notices"
1604
  msgstr ""
1605
 
1606
+ #: templates/connect.php:380, templates/connect.php:398
1607
  msgid "Updates, announcements, marketing, no spam"
1608
  msgstr ""
1609
 
1610
+ #: templates/connect.php:387
1611
+ msgid "So you can reuse the license when the %s is no longer active."
1612
+ msgstr ""
1613
+
1614
+ #: templates/connect.php:388
1615
+ msgid "Current %s Status"
1616
  msgstr ""
1617
 
1618
+ #: templates/connect.php:389
1619
+ msgid "Active, deactivated, or uninstalled"
1620
  msgstr ""
1621
 
1622
+ #: templates/connect.php:397
1623
  msgid "Newsletter"
1624
  msgstr ""
1625
 
1626
+ #: templates/connect.php:405
1627
  msgid "Plugins & Themes"
1628
  msgstr ""
1629
 
1630
+ #: templates/connect.php:405
1631
+ msgid "optional"
1632
+ msgstr ""
1633
+
1634
+ #: templates/connect.php:406
1635
+ msgid "To help us troubleshoot any potential issues that may arise from other plugin or theme conflicts."
1636
+ msgstr ""
1637
+
1638
+ #: templates/connect.php:407
1639
  msgid "Title, slug, version, and is active"
1640
  msgstr ""
1641
 
1642
+ #: templates/connect.php:424
1643
+ msgid "The %1$s will periodically send %2$s to %3$s for security & feature updates delivery, and license management."
1644
  msgstr ""
1645
 
1646
  #: templates/connect.php:426
1647
+ msgid "diagnostic data"
1648
+ msgstr ""
1649
+
1650
+ #: templates/connect.php:427
1651
+ msgid "Freemius is our licensing and software updates engine"
1652
+ msgstr ""
1653
+
1654
+ #: templates/connect.php:430
1655
  msgid "What permissions are being granted?"
1656
  msgstr ""
1657
 
1658
+ #: templates/connect.php:457
1659
  msgid "Don't have a license key?"
1660
  msgstr ""
1661
 
1662
+ #: templates/connect.php:460
1663
  msgid "Have a license key?"
1664
  msgstr ""
1665
 
1666
+ #: templates/connect.php:468
1667
  msgid "Privacy Policy"
1668
  msgstr ""
1669
 
1670
+ #: templates/connect.php:470
1671
  msgid "License Agreement"
1672
  msgstr ""
1673
 
1674
+ #: templates/connect.php:470
1675
  msgid "Terms of Service"
1676
  msgstr ""
1677
 
1678
+ #: templates/connect.php:866
1679
  msgctxt "as in the process of sending an email"
1680
  msgid "Sending email"
1681
  msgstr ""
1682
 
1683
+ #: templates/connect.php:867
1684
  msgctxt "as activating plugin"
1685
  msgid "Activating"
1686
  msgstr ""
2269
  msgid "Update License"
2270
  msgstr ""
2271
 
2272
+ #: templates/forms/license-activation.php:41
2273
+ msgid "The %1$s will be periodically sending data to %2$s to check for security and feature updates, and verify the validity of your license."
2274
+ msgstr ""
2275
+
2276
+ #: templates/forms/license-activation.php:183
2277
  msgid "Associate with the license owner's account."
2278
  msgstr ""
2279
 
freemius/start.php CHANGED
@@ -15,7 +15,7 @@
15
  *
16
  * @var string
17
  */
18
- $this_sdk_version = '2.4.1';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
@@ -512,7 +512,7 @@
512
  }
513
 
514
  /**
515
- * @param array <string,string> $module Plugin or Theme details.
516
  *
517
  * @return Freemius
518
  * @throws Freemius_Exception
@@ -527,4 +527,4 @@
527
  function fs_dump_log() {
528
  FS_Logger::dump();
529
  }
530
- }
15
  *
16
  * @var string
17
  */
18
+ $this_sdk_version = '2.4.2';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
512
  }
513
 
514
  /**
515
+ * @param array <string,string|bool|array> $module Plugin or Theme details.
516
  *
517
  * @return Freemius
518
  * @throws Freemius_Exception
527
  function fs_dump_log() {
528
  FS_Logger::dump();
529
  }
530
+ }
freemius/templates/account.php CHANGED
@@ -21,7 +21,9 @@
21
  /**
22
  * @var FS_Plugin_Tag $update
23
  */
24
- $update = $fs->get_update( false, false, WP_FS__TIME_24_HOURS_IN_SEC / 24 );
 
 
25
 
26
  if ( is_object($update) ) {
27
  /**
@@ -433,11 +435,11 @@
433
  'value' => $fs->get_plugin_version()
434
  );
435
 
436
- if ( $is_premium && ! $is_whitelabeled ) {
437
  $profile[] = array(
438
  'id' => 'beta_program',
439
  'title' => '',
440
- 'value' => $user->is_beta
441
  );
442
  }
443
 
21
  /**
22
  * @var FS_Plugin_Tag $update
23
  */
24
+ $update = $fs->has_release_on_freemius() ?
25
+ $fs->get_update( false, false, WP_FS__TIME_24_HOURS_IN_SEC / 24 ) :
26
+ null;
27
 
28
  if ( is_object($update) ) {
29
  /**
435
  'value' => $fs->get_plugin_version()
436
  );
437
 
438
+ if ( ! fs_is_network_admin() && $is_premium && ! $is_whitelabeled ) {
439
  $profile[] = array(
440
  'id' => 'beta_program',
441
  'title' => '',
442
+ 'value' => $site->is_beta
443
  );
444
  }
445
 
freemius/templates/connect.php CHANGED
@@ -181,12 +181,7 @@
181
 
182
  $message = $fs->apply_filters(
183
  'connect-message_on-premium',
184
- ($is_network_upgrade_mode ?
185
- '' :
186
- /* translators: %s: name (e.g. Hey John,) */
187
- $hey_x_text . '<br>'
188
- ) .
189
- sprintf( fs_text_inline( 'Thanks for purchasing %s! To get started, please enter your license key:', 'thanks-for-purchasing', $slug ), '<b>' . $fs->get_plugin_name() . '</b>' ),
190
  $first_name,
191
  $fs->get_plugin_name()
192
  );
@@ -347,6 +342,9 @@
347
  } ?>><?php echo esc_html( $button_label ) ?></button>
348
  </form>
349
  <?php endif ?>
 
 
 
350
  </div><?php
351
 
352
  // Set core permission list items.
@@ -367,26 +365,30 @@
367
  );
368
  }
369
 
370
- $permissions['site'] = array(
371
- 'icon-class' => 'dashicons dashicons-admin-settings',
372
- 'label' => $fs->get_text_inline( 'Your Site Overview', 'permissions-site' ),
373
- 'desc' => $fs->get_text_inline( 'Site URL, WP version, PHP info', 'permissions-site_desc' ),
374
- 'priority' => 10,
375
- );
376
-
377
- $permissions['notices'] = array(
378
- 'icon-class' => 'dashicons dashicons-testimonial',
379
- 'label' => $fs->get_text_inline( 'Admin Notices', 'permissions-admin-notices' ),
380
- 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
381
- 'priority' => 13,
382
- );
 
 
 
383
 
384
- $permissions['events'] = array(
385
- 'icon-class' => 'dashicons dashicons-admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
386
- 'label' => sprintf( $fs->get_text_inline( 'Current %s Events', 'permissions-events' ), ucfirst( $fs->get_module_type() ) ),
387
- 'desc' => $fs->get_text_inline( 'Activation, deactivation and uninstall', 'permissions-events_desc' ),
388
- 'priority' => 20,
389
- );
 
390
 
391
  // Add newsletter permissions if enabled.
392
  if ( $is_gdpr_required || $fs->is_permission_requested( 'newsletter' ) ) {
@@ -398,14 +400,15 @@
398
  );
399
  }
400
 
401
- $permissions['extensions'] = array(
402
  'icon-class' => 'dashicons dashicons-menu',
403
- 'label' => $fs->get_text_inline( 'Plugins & Themes', 'permissions-extensions' ),
 
404
  'desc' => $fs->get_text_inline( 'Title, slug, version, and is active', 'permissions-extensions_desc' ),
405
  'priority' => 25,
406
  'optional' => true,
407
- 'default' => $fs->apply_filters( 'permission_extensions_default', true )
408
- );
409
 
410
  // Allow filtering of the permissions list.
411
  $permissions = $fs->apply_filters( 'permission_list', $permissions );
@@ -417,13 +420,15 @@
417
  <div class="fs-permissions">
418
  <?php if ( $require_license_key ) : ?>
419
  <p class="fs-license-sync-disclaimer"><?php
420
- echo sprintf(
421
- fs_esc_html_inline( 'The %1$s will be periodically sending data to %2$s to check for security and feature updates, and verify the validity of your license.', 'license-sync-disclaimer', $slug ),
422
  $fs->get_module_label( true ),
423
- $freemius_link
 
424
  ) ?></p>
425
- <?php endif ?>
426
  <a class="fs-trigger" href="#" tabindex="1"><?php fs_esc_html_echo_inline( 'What permissions are being granted?', 'what-permissions', $slug ) ?></a>
 
427
  <ul><?php
428
  foreach ( $permissions as $id => $permission ) : ?>
429
  <li id="fs-permission-<?php echo esc_attr( $id ); ?>"
@@ -436,7 +441,7 @@
436
  <?php endif ?>
437
 
438
  <div class="fs-permission-description">
439
- <span><?php echo esc_html( $permission['label'] ); ?></span>
440
 
441
  <p><?php echo esc_html( $permission['desc'] ); ?></p>
442
  </div>
@@ -702,9 +707,16 @@
702
  var ajaxOptin = ( requireLicenseKey || isNetworkActive );
703
 
704
  $form.on('submit', function () {
705
- var isExtensionsTrackingAllowed = $( '#fs-permission-extensions .fs-switch' ).hasClass( 'fs-on' );
706
-
707
- $( 'input[name=is_extensions_tracking_allowed]' ).val( isExtensionsTrackingAllowed ? 1 : 0 );
 
 
 
 
 
 
 
708
 
709
  /**
710
  * @author Vova Feldman (@svovaf)
181
 
182
  $message = $fs->apply_filters(
183
  'connect-message_on-premium',
184
+ sprintf( fs_text_inline( 'Welcome to %s! To get started, please enter your license key:', 'thanks-for-purchasing', $slug ), '<b>' . $fs->get_plugin_name() . '</b>' ),
 
 
 
 
 
185
  $first_name,
186
  $fs->get_plugin_name()
187
  );
342
  } ?>><?php echo esc_html( $button_label ) ?></button>
343
  </form>
344
  <?php endif ?>
345
+ <?php if ( $require_license_key ) : ?>
346
+ <a id="license_issues_link" href="<?php echo $fs->apply_filters( 'known_license_issues_url', 'https://freemius.com/help/documentation/wordpress-sdk/license-activation-issues/' ) ?>" target="_blank"><?php fs_esc_html_echo_inline( 'License issues?', 'license-issues', $slug ) ?></a>
347
+ <?php endif ?>
348
  </div><?php
349
 
350
  // Set core permission list items.
365
  );
366
  }
367
 
368
+ $permissions['site'] = array(
369
+ 'icon-class' => 'dashicons dashicons-admin-settings',
370
+ 'tooltip' => ( $require_license_key ? sprintf( $fs->get_text_inline( 'So you can manage and control your license remotely from the User Dashboard.', 'permissions-site_tooltip' ), $fs->get_module_type() ) : '' ),
371
+ 'label' => $fs->get_text_inline( 'Your Site Overview', 'permissions-site' ),
372
+ 'desc' => $fs->get_text_inline( 'Site URL, WP version, PHP info', 'permissions-site_desc' ),
373
+ 'priority' => 10,
374
+ );
375
+
376
+ if ( ! $require_license_key ) {
377
+ $permissions['notices'] = array(
378
+ 'icon-class' => 'dashicons dashicons-testimonial',
379
+ 'label' => $fs->get_text_inline( 'Admin Notices', 'permissions-admin-notices' ),
380
+ 'desc' => $fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
381
+ 'priority' => 13,
382
+ );
383
+ }
384
 
385
+ $permissions['events'] = array(
386
+ 'icon-class' => 'dashicons dashicons-admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
387
+ 'tooltip' => ( $require_license_key ? sprintf( $fs->get_text_inline( 'So you can reuse the license when the %s is no longer active.', 'permissions-events_tooltip' ), $fs->get_module_type() ) : '' ),
388
+ 'label' => sprintf( $fs->get_text_inline( 'Current %s Status', 'permissions-events' ), ucfirst( $fs->get_module_type() ) ),
389
+ 'desc' => $fs->get_text_inline( 'Active, deactivated, or uninstalled', 'permissions-events_desc' ),
390
+ 'priority' => 20,
391
+ );
392
 
393
  // Add newsletter permissions if enabled.
394
  if ( $is_gdpr_required || $fs->is_permission_requested( 'newsletter' ) ) {
400
  );
401
  }
402
 
403
+ $permissions['extensions'] = array(
404
  'icon-class' => 'dashicons dashicons-menu',
405
+ 'label' => $fs->get_text_inline( 'Plugins & Themes', 'permissions-extensions' ) . ( $require_license_key ? ' (' . $fs->get_text_inline( 'optional' ) . ')' : '' ),
406
+ 'tooltip' => $fs->get_text_inline( 'To help us troubleshoot any potential issues that may arise from other plugin or theme conflicts.', 'permissions-events_tooltip' ),
407
  'desc' => $fs->get_text_inline( 'Title, slug, version, and is active', 'permissions-extensions_desc' ),
408
  'priority' => 25,
409
  'optional' => true,
410
+ 'default' => $fs->apply_filters( 'permission_extensions_default', ! $require_license_key )
411
+ );
412
 
413
  // Allow filtering of the permissions list.
414
  $permissions = $fs->apply_filters( 'permission_list', $permissions );
420
  <div class="fs-permissions">
421
  <?php if ( $require_license_key ) : ?>
422
  <p class="fs-license-sync-disclaimer"><?php
423
+ echo sprintf(
424
+ fs_esc_html_inline( 'The %1$s will periodically send %2$s to %3$s for security & feature updates delivery, and license management.', 'license-sync-disclaimer', $slug ),
425
  $fs->get_module_label( true ),
426
+ sprintf('<a class="fs-trigger" href="#" tabindex="1">%s</a>', fs_esc_html_inline('diagnostic data', 'send-data')),
427
+ '<a class="fs-tooltip-trigger' . (is_rtl() ? ' rtl' : '') . '" href="' . $freemius_site_url . '" target="_blank" rel="noopener" tabindex="1">freemius.com <i class="dashicons dashicons-editor-help" style="text-decoration: none;"><span class="fs-tooltip" style="width: 170px">' . $fs->get_text_inline( 'Freemius is our licensing and software updates engine', 'permissions-extensions_desc' ) . '</span></i></a>'
428
  ) ?></p>
429
+ <?php else : ?>
430
  <a class="fs-trigger" href="#" tabindex="1"><?php fs_esc_html_echo_inline( 'What permissions are being granted?', 'what-permissions', $slug ) ?></a>
431
+ <?php endif ?>
432
  <ul><?php
433
  foreach ( $permissions as $id => $permission ) : ?>
434
  <li id="fs-permission-<?php echo esc_attr( $id ); ?>"
441
  <?php endif ?>
442
 
443
  <div class="fs-permission-description">
444
+ <span<?php if ( ! empty($permission['tooltip']) ) : ?> class="fs-tooltip-trigger"<?php endif ?>><?php echo esc_html( $permission['label'] ); ?><?php if ( ! empty($permission['tooltip']) ) : ?><i class="dashicons dashicons-editor-help"><span class="fs-tooltip" style="width: 200px"><?php echo $permission['tooltip'] ?></span></i><?php endif ?></span>
445
 
446
  <p><?php echo esc_html( $permission['desc'] ); ?></p>
447
  </div>
707
  var ajaxOptin = ( requireLicenseKey || isNetworkActive );
708
 
709
  $form.on('submit', function () {
710
+ var $extensionsPermission = $('#fs-permission-extensions .fs-switch'),
711
+ isExtensionsTrackingAllowed = ($extensionsPermission.length > 0) ?
712
+ $extensionsPermission.hasClass('fs-on') :
713
+ null;
714
+
715
+ if (null === isExtensionsTrackingAllowed) {
716
+ $('input[name=is_extensions_tracking_allowed]').remove();
717
+ } else {
718
+ $('input[name=is_extensions_tracking_allowed]').val(isExtensionsTrackingAllowed ? 1 : 0);
719
+ }
720
 
721
  /**
722
  * @author Vova Feldman (@svovaf)
freemius/templates/forms/affiliation.php CHANGED
@@ -1,509 +1,509 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2015, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.2.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- * @var Freemius $fs
16
- */
17
- $fs = freemius( $VARS['id'] );
18
-
19
- $slug = $fs->get_slug();
20
-
21
- $user = $fs->get_user();
22
- $affiliate = $fs->get_affiliate();
23
- $affiliate_terms = $fs->get_affiliate_terms();
24
-
25
- $plugin_title = $fs->get_plugin_title();
26
- $module_type = $fs->is_plugin() ?
27
- WP_FS__MODULE_TYPE_PLUGIN :
28
- WP_FS__MODULE_TYPE_THEME;
29
-
30
- $commission = $affiliate_terms->get_formatted_commission();
31
-
32
- $readonly = false;
33
- $is_affiliate = is_object( $affiliate );
34
- $is_pending_affiliate = false;
35
- $email_address = ( is_object( $user ) ?
36
- $user->email :
37
- '' );
38
- $full_name = ( is_object( $user ) ?
39
- $user->get_name() :
40
- '' );
41
- $paypal_email_address = '';
42
- $domain = '';
43
- $extra_domains = array();
44
- $promotion_method_social_media = false;
45
- $promotion_method_mobile_apps = false;
46
- $statistics_information = false;
47
- $promotion_method_description = false;
48
- $members_dashboard_login_url = 'https://members.freemius.com/login/';
49
-
50
- $affiliate_application_data = $fs->get_affiliate_application_data();
51
-
52
- if ( $is_affiliate && $affiliate->is_pending() ) {
53
- $readonly = 'readonly';
54
- $is_pending_affiliate = true;
55
-
56
- $paypal_email_address = $affiliate->paypal_email;
57
- $domain = $affiliate->domain;
58
- $statistics_information = $affiliate_application_data['stats_description'];
59
- $promotion_method_description = $affiliate_application_data['promotion_method_description'];
60
-
61
- if ( ! empty( $affiliate_application_data['additional_domains'] ) ) {
62
- $extra_domains = $affiliate_application_data['additional_domains'];
63
- }
64
-
65
- if ( ! empty( $affiliate_application_data['promotion_methods'] ) ) {
66
- $promotion_methods = explode( ',', $affiliate_application_data['promotion_methods'] );
67
- $promotion_method_social_media = in_array( 'social_media', $promotion_methods );
68
- $promotion_method_mobile_apps = in_array( 'mobile_apps', $promotion_methods );
69
- }
70
- } else {
71
- $current_user = Freemius::_get_current_wp_user();
72
- $full_name = trim( $current_user->user_firstname . ' ' . $current_user->user_lastname );
73
- $email_address = $current_user->user_email;
74
- $domain = fs_strip_url_protocol( get_site_url() );
75
- }
76
-
77
- $affiliate_tracking = 30;
78
-
79
- if ( is_object( $affiliate_terms ) ) {
80
- $affiliate_tracking = ( ! is_null( $affiliate_terms->cookie_days ) ?
81
- ( $affiliate_terms->cookie_days . '-day' ) :
82
- fs_text_inline( 'Non-expiring', 'non-expiring', $slug ) );
83
- }
84
-
85
- $apply_to_become_affiliate_text = fs_text_inline( 'Apply to become an affiliate', 'apply-to-become-an-affiliate', $slug );
86
-
87
- $module_id = $fs->get_id();
88
- $affiliate_program_terms_url = "https://freemius.com/plugin/{$module_id}/{$slug}/legal/affiliate-program/";
89
- ?>
90
- <div id="fs_affiliation_content_wrapper" class="wrap">
91
- <form method="post" action="">
92
- <div id="poststuff">
93
- <div class="postbox">
94
- <div class="inside">
95
- <div id="messages">
96
- <div id="error_message" class="error" style="display: none">
97
- <p><strong></strong></p>
98
- </div>
99
- <div id="message" class="updated" style="display: none">
100
- <p><strong></strong></p>
101
- </div>
102
- <?php if ( $is_affiliate ) : ?>
103
- <?php if ( $affiliate->is_active() ) : ?>
104
- <div class="updated">
105
- <p><strong><?php
106
- echo sprintf(
107
- fs_esc_html_inline( "Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.", 'affiliate-application-accepted', $slug ),
108
- $plugin_title,
109
- sprintf(
110
- '<a href="%s" target="_blank" rel="noopener">%s</a>',
111
- $members_dashboard_login_url,
112
- $members_dashboard_login_url
113
- )
114
- );
115
- ?></strong></p>
116
- </div>
117
- <?php else : ?>
118
- <?php
119
- $message_text = '';
120
-
121
- if ( $is_pending_affiliate ) {
122
- $message_text = fs_text_inline( "Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.", 'affiliate-application-thank-you', $slug );
123
- $message_container_class = 'updated';
124
- } else if ( $affiliate->is_suspended() ) {
125
- $message_text = fs_text_inline( 'Your affiliation account was temporarily suspended.', 'affiliate-account-suspended', $slug );
126
- $message_container_class = 'notice notice-warning';
127
- } else if ( $affiliate->is_rejected() ) {
128
- $message_text = fs_text_inline( "Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.", 'affiliate-application-rejected', $slug );
129
- $message_container_class = 'error';
130
- } else if ( $affiliate->is_blocked() ) {
131
- $message_text = fs_text_inline( 'Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.', 'affiliate-account-blocked', $slug );
132
- $message_container_class = 'error';
133
- }
134
- ?>
135
- <div class="<?php echo $message_container_class ?>">
136
- <p><strong><?php echo esc_html( $message_text ) ?></strong></p>
137
- </div>
138
- <?php endif ?>
139
- <?php endif ?>
140
- </div>
141
- <div class="entry-content">
142
- <?php if ( ! $is_affiliate ) : ?>
143
- <div id="application_messages_container">
144
- <p><?php echo esc_html( sprintf( fs_text_inline( 'Like the %s? Become our ambassador and earn cash ;-)', 'become-an-ambassador', $slug ), $module_type ) ) ?></p>
145
- <p><?php echo esc_html( sprintf( fs_text_inline( 'Refer new customers to our %s and earn %s commission on each successful sale you refer!', 'refer-new-customers', $slug ), $module_type, $commission ) ) ?></p>
146
- </div>
147
- <?php endif ?>
148
- <h3><?php fs_esc_html_echo_inline( 'Program Summary', 'program-summary', $slug ) ?></h3>
149
- <ul>
150
- <li><?php echo esc_html( sprintf( fs_text_inline( '%s commission when a customer purchases a new license.', 'commission-on-new-license-purchase', $slug ), $commission ) ) ?></li>
151
- <?php if ( is_object( $affiliate_terms ) && $affiliate_terms->has_renewals_commission() ) : ?>
152
- <li><?php echo esc_html( sprintf( fs_text_inline( 'Get commission for automated subscription renewals.', 'renewals-commission', $slug ) ) ) ?></li>
153
- <?php endif ?>
154
- <?php if ( is_object( $affiliate_terms ) && ( ! $affiliate_terms->is_session_cookie() ) ) : ?>
155
- <li><?php echo esc_html( sprintf( fs_text_inline( '%s tracking cookie after the first visit to maximize earnings potential.', 'affiliate-tracking', $slug ), $affiliate_tracking ) ) ?></li>
156
- <?php endif ?>
157
- <?php if ( is_object( $affiliate_terms ) && $affiliate_terms->has_lifetime_commission() ) : ?>
158
- <li><?php fs_esc_html_echo_inline( 'Unlimited commissions.', 'unlimited-commissions', $slug ) ?></li>
159
- <?php endif ?>
160
- <li><?php echo esc_html( sprintf( fs_text_inline( '%s minimum payout amount.', 'minimum-payout-amount', $slug ), '$100' ) ) ?></li>
161
- <li><?php fs_esc_html_echo_inline( 'Payouts are in USD and processed monthly via PayPal.', 'payouts-unit-and-processing', $slug ) ?></li>
162
- <li><?php fs_esc_html_echo_inline( 'As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.', 'commission-payment', $slug ) ?></li>
163
- </ul>
164
- <div id="application_form_container" <?php echo ( $is_pending_affiliate ) ? '' : 'style="display: none"' ?>>
165
- <h3><?php fs_esc_html_echo_inline( 'Affiliate', 'affiliate', $slug ) ?></h3>
166
- <form>
167
- <div class="input-container input-container-text">
168
- <label class="input-label"><?php fs_esc_html_echo_inline( 'Email address', 'email-address', $slug ) ?></label>
169
- <input id="email_address" type="text" value="<?php echo esc_attr( $email_address ) ?>" class="regular-text" <?php echo ( $readonly || is_object( $user ) ) ? 'readonly' : '' ?>>
170
- </div>
171
- <div class="input-container input-container-text">
172
- <label class="input-label"><?php fs_esc_html_echo_inline( 'Full name', 'full-name', $slug ) ?></label>
173
- <input id="full_name" type="text" value="<?php echo esc_attr( $full_name ) ?>" class="regular-text" <?php echo $readonly ?>>
174
- </div>
175
- <div class="input-container input-container-text">
176
- <label class="input-label"><?php fs_esc_html_echo_inline( 'PayPal account email address', 'paypal-account-email-address', $slug ) ?></label>
177
- <input id="paypal_email" type="text" value="<?php echo esc_attr( $paypal_email_address ) ?>" class="regular-text" <?php echo $readonly ?>>
178
- </div>
179
- <div class="input-container input-container-text">
180
- <label class="input-label"><?php echo esc_html( sprintf( fs_text_inline( 'Where are you going to promote the %s?', 'domain-field-label', $slug ), $module_type ) ) ?></label>
181
- <input id="domain" type="text" value="<?php echo esc_attr( $domain ) ?>" class="domain regular-text" <?php echo $readonly ?>>
182
- <p class="description"><?php echo esc_html( sprintf( fs_text_inline( 'Enter the domain of your website or other websites from where you plan to promote the %s.', 'domain-field-desc', $slug ), $module_type ) ) ?></p>
183
- <?php if ( ! $is_affiliate ) : ?>
184
- <a id="add_domain" href="#" class="disabled">+ <?php fs_esc_html_echo_inline( 'Add another domain', 'add-another-domain', $slug ) ?>...</a>
185
- <?php endif ?>
186
- </div>
187
- <div id="extra_domains_container" class="input-container input-container-text" <?php echo $is_pending_affiliate ? '' : 'style="display: none"' ?>>
188
- <label class="input-label"><?php fs_esc_html_echo_inline( 'Extra Domains', 'extra-domain-fields-label', $slug ) ?></label>
189
- <p class="description"><?php fs_esc_html_echo_inline( 'Extra domains where you will be marketing the product from.', 'extra-domain-fields-desc', $slug ) ?></p>
190
- <?php if ( $is_pending_affiliate && ! empty( $extra_domains ) ) : ?>
191
- <?php foreach ( $extra_domains as $extra_domain ) : ?>
192
- <div class="extra-domain-input-container">
193
- <input type="text" value="<?php echo esc_attr( $extra_domain ) ?>" class="domain regular-text" <?php echo $readonly ?>>
194
- </div>
195
- <?php endforeach ?>
196
- <?php endif ?>
197
- </div>
198
- <div class="input-container">
199
- <label class="input-label"><?php fs_esc_html_echo_inline( 'Promotion methods', 'promotion-methods', $slug ) ?></label>
200
- <div>
201
- <input id="promotion_method_social_media" type="checkbox" <?php checked( $promotion_method_social_media ) ?> <?php disabled( $is_affiliate ) ?>/>
202
- <label for="promotion_method_social_media"><?php fs_esc_html_echo_inline( 'Social media (Facebook, Twitter, etc.)', 'social-media', $slug ) ?></label>
203
- </div>
204
- <div>
205
- <input id="promotion_method_mobile_apps" type="checkbox" <?php checked( $promotion_method_mobile_apps ) ?> <?php disabled( $is_affiliate ) ?>/>
206
- <label for="promotion_method_mobile_apps"><?php fs_esc_html_echo_inline( 'Mobile apps', 'mobile-apps', $slug ) ?></label>
207
- </div>
208
- </div>
209
- <div class="input-container input-container-text">
210
- <label class="input-label"><nobr><?php fs_esc_html_echo_inline( 'Website, email, and social media statistics (optional)', 'statistics-information-field-label', $slug ) ?></nobr></label>
211
- <textarea id="statistics_information" rows="5" <?php echo $readonly ?> class="regular-text"><?php echo $statistics_information ?></textarea>
212
- <?php if ( ! $is_affiliate ) : ?>
213
- <p class="description"><?php fs_esc_html_echo_inline( 'Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).', 'statistics-information-field-desc', $slug ) ?></p>
214
- <?php endif ?>
215
- </div>
216
- <div class="input-container input-container-text">
217
- <label class="input-label"><?php fs_esc_html_echo_inline( 'How will you promote us?', 'promotion-method-desc-field-label', $slug ) ?></label>
218
- <textarea id="promotion_method_description" rows="5" <?php echo $readonly ?> class="regular-text"><?php echo $promotion_method_description ?></textarea>
219
- <?php if ( ! $is_affiliate ) : ?>
220
- <p class="description"><?php echo esc_html( sprintf( fs_text_inline( 'Please provide details on how you intend to promote %s (please be as specific as possible).', 'promotion-method-desc-field-desc', $slug ), $plugin_title ) ) ?></p>
221
- <?php endif ?>
222
- </div>
223
- <?php if ( ! $is_affiliate ) : ?>
224
- <div>
225
- <input type="checkbox" id="legal_consent_checkbox">
226
- <label for="legal_consent_checkbox">I agree to the <a href="<?php echo $affiliate_program_terms_url ?>" target="_blank" rel="noopener">Referrer Program</a>'s terms & conditions.</label>
227
- </div>
228
- <?php endif ?>
229
- </form>
230
- </div>
231
- <?php if ( ! $is_affiliate ) : ?>
232
- <a id="cancel_button" href="#" class="button button-secondary button-cancel" style="display: none"><?php fs_esc_html_echo_inline( 'Cancel', 'cancel', $slug ) ?></a>
233
- <a id="submit_button" class="button button-primary disabled" href="#" style="display: none"><?php echo esc_html( $apply_to_become_affiliate_text ) ?></a>
234
- <a id="apply_button" class="button button-primary" href="#"><?php fs_esc_html_echo_inline( 'Become an affiliate', 'become-an-affiliate', $slug ) ?></a>
235
- <?php endif ?>
236
- </div>
237
- </div>
238
- </div>
239
- </div>
240
- </form>
241
- <script type="text/javascript">
242
- jQuery(function ($) {
243
- var
244
- $contentWrapper = $('#fs_affiliation_content_wrapper'),
245
- $socialMedia = $('#promotion_method_social_media'),
246
- $mobileApps = $('#promotion_method_mobile_apps'),
247
- $applyButton = $('#apply_button'),
248
- $submitButton = $('#submit_button'),
249
- $cancelButton = $('#cancel_button'),
250
- $applicationFormContainer = $('#application_form_container'),
251
- $errorMessageContainer = $('#error_message'),
252
- $domain = $('#domain'),
253
- $addDomain = $('#add_domain'),
254
- $extraDomainsContainer = $('#extra_domains_container'),
255
- $legalConsentCheckbox = $( '#legal_consent_checkbox' );
256
-
257
- $applyButton.click(function (evt) {
258
- evt.preventDefault();
259
-
260
- var $this = $(this);
261
- $this.hide();
262
-
263
- $applicationFormContainer.show();
264
- $cancelButton.show();
265
- $submitButton.show();
266
-
267
- $contentWrapper.find('input[type="text"]:first').focus();
268
- });
269
-
270
- $submitButton.click(function (evt) {
271
- evt.preventDefault();
272
-
273
- var $this = $(this);
274
-
275
- if ($this.hasClass('disabled')) {
276
- return;
277
- }
278
-
279
- $errorMessageContainer.hide();
280
-
281
- var
282
- $emailAddress = $('#email_address'),
283
- emailAddress = null,
284
- paypalEmailAddress = $('#paypal_email').val().trim();
285
-
286
- if (1 === $emailAddress.length) {
287
- emailAddress = $emailAddress.val().trim();
288
-
289
- if (0 === emailAddress.length) {
290
- showErrorMessage('<?php fs_esc_js_echo_inline( 'Email address is required.', 'email-address-is-required', $slug ) ?>');
291
- return;
292
- }
293
- }
294
-
295
- if (0 === paypalEmailAddress.length) {
296
- showErrorMessage('<?php fs_esc_js_echo_inline( 'PayPal email address is required.', 'paypal-email-address-is-required', $slug ) ?>');
297
- return;
298
- }
299
-
300
- var
301
- $extraDomains = $extraDomainsContainer.find('.domain'),
302
- domain = $domain.val().trim().toLowerCase(),
303
- extraDomains = [];
304
-
305
- if (0 === domain.length) {
306
- showErrorMessage('<?php fs_esc_js_echo_inline( 'Domain is required.', 'domain-is-required', $slug ) ?>');
307
- return;
308
- } else if ('freemius.com' === domain) {
309
- showErrorMessage('<?php fs_esc_js_echo_inline( 'Invalid domain', 'invalid-domain', $slug ) ?>' + ' [' + domain + '].');
310
- return;
311
- }
312
-
313
- if ($extraDomains.length > 0) {
314
- var hasError = false;
315
-
316
- $extraDomains.each(function () {
317
- var
318
- $this = $(this),
319
- extraDomain = $this.val().trim().toLowerCase();
320
- if (0 === extraDomain.length || extraDomain === domain) {
321
- return true;
322
- } else if ('freemius.com' === extraDomain) {
323
- showErrorMessage('<?php fs_esc_js_echo_inline( 'Invalid domain', 'invalid-domain', $slug ) ?>' + ' [' + extraDomain + '].');
324
- hasError = true;
325
- return false;
326
- }
327
-
328
- extraDomains.push(extraDomain);
329
- });
330
-
331
- if (hasError) {
332
- return;
333
- }
334
- }
335
-
336
- var
337
- promotionMethods = [],
338
- statisticsInformation = $('#statistics_information').val(),
339
- promotionMethodDescription = $('#promotion_method_description').val();
340
-
341
- if ($socialMedia.attr('checked')) {
342
- promotionMethods.push('social_media');
343
- }
344
-
345
- if ($mobileApps.attr('checked')) {
346
- promotionMethods.push('mobile_apps');
347
- }
348
-
349
- var affiliate = {
350
- full_name : $('#full_name').val().trim(),
351
- paypal_email : paypalEmailAddress,
352
- stats_description : statisticsInformation,
353
- promotion_method_description: promotionMethodDescription
354
- };
355
-
356
- if (null !== emailAddress) {
357
- affiliate.email = emailAddress;
358
- }
359
-
360
- affiliate.domain = domain;
361
- affiliate.additional_domains = extraDomains;
362
-
363
- if (promotionMethods.length > 0) {
364
- affiliate.promotion_methods = promotionMethods.join(',');
365
- }
366
-
367
- $.ajax({
368
- url : ajaxurl,
369
- method : 'POST',
370
- data : {
371
- action : '<?php echo $fs->get_ajax_action( 'submit_affiliate_application' ) ?>',
372
- security : '<?php echo $fs->get_ajax_security( 'submit_affiliate_application' ) ?>',
373
- module_id: '<?php echo $module_id ?>',
374
- affiliate: affiliate
375
- },
376
- beforeSend: function () {
377
- $cancelButton.addClass('disabled');
378
- $submitButton.addClass('disabled');
379
- $submitButton.text('<?php fs_esc_js_echo_inline( 'Submitting', 'submitting' ) ?>...');
380
- },
381
- success : function (result) {
382
- if (result.success) {
383
- location.reload();
384
- } else {
385
- if (result.error && result.error.length > 0) {
386
- showErrorMessage(result.error);
387
- }
388
-
389
- $cancelButton.removeClass('disabled');
390
- $submitButton.removeClass('disabled');
391
- $submitButton.text('<?php echo esc_js( $apply_to_become_affiliate_text ) ?>')
392
- }
393
- }
394
- });
395
- });
396
-
397
- $cancelButton.click(function (evt) {
398
- evt.preventDefault();
399
-
400
- var $this = $(this);
401
-
402
- if ($this.hasClass('disabled')) {
403
- return;
404
- }
405
-
406
- $applicationFormContainer.hide();
407
- $this.hide();
408
- $submitButton.hide();
409
-
410
- $applyButton.show();
411
-
412
- window.scrollTo(0, 0);
413
- });
414
-
415
- $domain.on('input propertychange', onDomainChange);
416
-
417
- $addDomain.click(function (evt) {
418
- evt.preventDefault();
419
-
420
- var
421
- $this = $(this),
422
- domain = $domain.val().trim();
423
-
424
- if ($this.hasClass('disabled') || 0 === domain.length) {
425
- return;
426
- }
427
-
428
- $domain.off('input propertychange');
429
- $this.addClass('disabled');
430
-
431
- var
432
- $extraDomainInputContainer = $('<div class="extra-domain-input-container"><input type="text" class="domain regular-text"/></div>'),
433
- $extraDomainInput = $extraDomainInputContainer.find('input'),
434
- $removeDomain = $('<a href="#" class="remove-domain"><i class="dashicons dashicons-no" title="<?php fs_esc_js_echo_inline( 'Remove', 'remove', $slug ) ?>"></i></a>');
435
-
436
- $extraDomainInputContainer.append($removeDomain);
437
-
438
- $extraDomainInput.on('input propertychange', onDomainChange);
439
-
440
- $removeDomain.click(function (evt) {
441
- evt.preventDefault();
442
-
443
- var
444
- $extraDomainInputs = $('.extra-domain-input-container .domain');
445
-
446
- if (1 === $extraDomainInputs.length)
447
- $extraDomainInputs.val('').focus();
448
- else
449
- $(this).parent().remove();
450
- });
451
-
452
- $extraDomainsContainer.show();
453
-
454
- $extraDomainInputContainer.appendTo($extraDomainsContainer);
455
- $extraDomainInput.focus();
456
-
457
- $this.appendTo($extraDomainsContainer);
458
- });
459
-
460
- /**
461
- * @author Leo Fajardo (@leorw)
462
- */
463
- function onDomainChange() {
464
- var
465
- domain = $(this).val().trim();
466
-
467
- if (domain.length > 0) {
468
- $addDomain.removeClass('disabled');
469
- } else {
470
- $addDomain.addClass('disabled');
471
- }
472
- }
473
-
474
- /**
475
- * @author Leo Fajardo (@leorw)
476
- *
477
- * @param {String} message
478
- */
479
- function showErrorMessage(message) {
480
- $errorMessageContainer.find('strong').text(message);
481
- $errorMessageContainer.show();
482
-
483
- window.scrollTo(0, 0);
484
- }
485
-
486
- /**
487
- * @author Xiaheng Chen (@xhchen)
488
- *
489
- * @since 2.4.0
490
- */
491
- $legalConsentCheckbox.click( function () {
492
- if ( $( this ).prop( 'checked' ) ) {
493
- $submitButton.removeClass( 'disabled' );
494
- } else {
495
- $submitButton.addClass( 'disabled' );
496
- }
497
- } );
498
- });
499
- </script>
500
- </div>
501
- <?php
502
- $params = array(
503
- 'page' => 'affiliation',
504
- 'module_id' => $module_id,
505
- 'module_slug' => $slug,
506
- 'module_version' => $fs->get_plugin_version(),
507
- );
508
- fs_require_template( 'powered-by.php', $params );
509
  ?>
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2015, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.2.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ * @var Freemius $fs
16
+ */
17
+ $fs = freemius( $VARS['id'] );
18
+
19
+ $slug = $fs->get_slug();
20
+
21
+ $user = $fs->get_user();
22
+ $affiliate = $fs->get_affiliate();
23
+ $affiliate_terms = $fs->get_affiliate_terms();
24
+
25
+ $plugin_title = $fs->get_plugin_title();
26
+ $module_type = $fs->is_plugin() ?
27
+ WP_FS__MODULE_TYPE_PLUGIN :
28
+ WP_FS__MODULE_TYPE_THEME;
29
+
30
+ $commission = $affiliate_terms->get_formatted_commission();
31
+
32
+ $readonly = false;
33
+ $is_affiliate = is_object( $affiliate );
34
+ $is_pending_affiliate = false;
35
+ $email_address = ( is_object( $user ) ?
36
+ $user->email :
37
+ '' );
38
+ $full_name = ( is_object( $user ) ?
39
+ $user->get_name() :
40
+ '' );
41
+ $paypal_email_address = '';
42
+ $domain = '';
43
+ $extra_domains = array();
44
+ $promotion_method_social_media = false;
45
+ $promotion_method_mobile_apps = false;
46
+ $statistics_information = false;
47
+ $promotion_method_description = false;
48
+ $members_dashboard_login_url = 'https://members.freemius.com/login/';
49
+
50
+ $affiliate_application_data = $fs->get_affiliate_application_data();
51
+
52
+ if ( $is_affiliate && $affiliate->is_pending() ) {
53
+ $readonly = 'readonly';
54
+ $is_pending_affiliate = true;
55
+
56
+ $paypal_email_address = $affiliate->paypal_email;
57
+ $domain = $affiliate->domain;
58
+ $statistics_information = $affiliate_application_data['stats_description'];
59
+ $promotion_method_description = $affiliate_application_data['promotion_method_description'];
60
+
61
+ if ( ! empty( $affiliate_application_data['additional_domains'] ) ) {
62
+ $extra_domains = $affiliate_application_data['additional_domains'];
63
+ }
64
+
65
+ if ( ! empty( $affiliate_application_data['promotion_methods'] ) ) {
66
+ $promotion_methods = explode( ',', $affiliate_application_data['promotion_methods'] );
67
+ $promotion_method_social_media = in_array( 'social_media', $promotion_methods );
68
+ $promotion_method_mobile_apps = in_array( 'mobile_apps', $promotion_methods );
69
+ }
70
+ } else {
71
+ $current_user = Freemius::_get_current_wp_user();
72
+ $full_name = trim( $current_user->user_firstname . ' ' . $current_user->user_lastname );
73
+ $email_address = $current_user->user_email;
74
+ $domain = fs_strip_url_protocol( get_site_url() );
75
+ }
76
+
77
+ $affiliate_tracking = 30;
78
+
79
+ if ( is_object( $affiliate_terms ) ) {
80
+ $affiliate_tracking = ( ! is_null( $affiliate_terms->cookie_days ) ?
81
+ ( $affiliate_terms->cookie_days . '-day' ) :
82
+ fs_text_inline( 'Non-expiring', 'non-expiring', $slug ) );
83
+ }
84
+
85
+ $apply_to_become_affiliate_text = fs_text_inline( 'Apply to become an affiliate', 'apply-to-become-an-affiliate', $slug );
86
+
87
+ $module_id = $fs->get_id();
88
+ $affiliate_program_terms_url = "https://freemius.com/plugin/{$module_id}/{$slug}/legal/affiliate-program/";
89
+ ?>
90
+ <div id="fs_affiliation_content_wrapper" class="wrap">
91
+ <form method="post" action="">
92
+ <div id="poststuff">
93
+ <div class="postbox">
94
+ <div class="inside">
95
+ <div id="messages">
96
+ <div id="error_message" class="error" style="display: none">
97
+ <p><strong></strong></p>
98
+ </div>
99
+ <div id="message" class="updated" style="display: none">
100
+ <p><strong></strong></p>
101
+ </div>
102
+ <?php if ( $is_affiliate ) : ?>
103
+ <?php if ( $affiliate->is_active() ) : ?>
104
+ <div class="updated">
105
+ <p><strong><?php
106
+ echo sprintf(
107
+ fs_esc_html_inline( "Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.", 'affiliate-application-accepted', $slug ),
108
+ $plugin_title,
109
+ sprintf(
110
+ '<a href="%s" target="_blank" rel="noopener">%s</a>',
111
+ $members_dashboard_login_url,
112
+ $members_dashboard_login_url
113
+ )
114
+ );
115
+ ?></strong></p>
116
+ </div>
117
+ <?php else : ?>
118
+ <?php
119
+ $message_text = '';
120
+
121
+ if ( $is_pending_affiliate ) {
122
+ $message_text = fs_text_inline( "Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.", 'affiliate-application-thank-you', $slug );
123
+ $message_container_class = 'updated';
124
+ } else if ( $affiliate->is_suspended() ) {
125
+ $message_text = fs_text_inline( 'Your affiliation account was temporarily suspended.', 'affiliate-account-suspended', $slug );
126
+ $message_container_class = 'notice notice-warning';
127
+ } else if ( $affiliate->is_rejected() ) {
128
+ $message_text = fs_text_inline( "Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.", 'affiliate-application-rejected', $slug );
129
+ $message_container_class = 'error';
130
+ } else if ( $affiliate->is_blocked() ) {
131
+ $message_text = fs_text_inline( 'Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.', 'affiliate-account-blocked', $slug );
132
+ $message_container_class = 'error';
133
+ }
134
+ ?>
135
+ <div class="<?php echo $message_container_class ?>">
136
+ <p><strong><?php echo esc_html( $message_text ) ?></strong></p>
137
+ </div>
138
+ <?php endif ?>
139
+ <?php endif ?>
140
+ </div>
141
+ <div class="entry-content">
142
+ <?php if ( ! $is_affiliate ) : ?>
143
+ <div id="application_messages_container">
144
+ <p><?php echo esc_html( sprintf( fs_text_inline( 'Like the %s? Become our ambassador and earn cash ;-)', 'become-an-ambassador', $slug ), $module_type ) ) ?></p>
145
+ <p><?php echo esc_html( sprintf( fs_text_inline( 'Refer new customers to our %s and earn %s commission on each successful sale you refer!', 'refer-new-customers', $slug ), $module_type, $commission ) ) ?></p>
146
+ </div>
147
+ <?php endif ?>
148
+ <h3><?php fs_esc_html_echo_inline( 'Program Summary', 'program-summary', $slug ) ?></h3>
149
+ <ul>
150
+ <li><?php echo esc_html( sprintf( fs_text_inline( '%s commission when a customer purchases a new license.', 'commission-on-new-license-purchase', $slug ), $commission ) ) ?></li>
151
+ <?php if ( is_object( $affiliate_terms ) && $affiliate_terms->has_renewals_commission() ) : ?>
152
+ <li><?php echo esc_html( sprintf( fs_text_inline( 'Get commission for automated subscription renewals.', 'renewals-commission', $slug ) ) ) ?></li>
153
+ <?php endif ?>
154
+ <?php if ( is_object( $affiliate_terms ) && ( ! $affiliate_terms->is_session_cookie() ) ) : ?>
155
+ <li><?php echo esc_html( sprintf( fs_text_inline( '%s tracking cookie after the first visit to maximize earnings potential.', 'affiliate-tracking', $slug ), $affiliate_tracking ) ) ?></li>
156
+ <?php endif ?>
157
+ <?php if ( is_object( $affiliate_terms ) && $affiliate_terms->has_lifetime_commission() ) : ?>
158
+ <li><?php fs_esc_html_echo_inline( 'Unlimited commissions.', 'unlimited-commissions', $slug ) ?></li>
159
+ <?php endif ?>
160
+ <li><?php echo esc_html( sprintf( fs_text_inline( '%s minimum payout amount.', 'minimum-payout-amount', $slug ), '$100' ) ) ?></li>
161
+ <li><?php fs_esc_html_echo_inline( 'Payouts are in USD and processed monthly via PayPal.', 'payouts-unit-and-processing', $slug ) ?></li>
162
+ <li><?php fs_esc_html_echo_inline( 'As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.', 'commission-payment', $slug ) ?></li>
163
+ </ul>
164
+ <div id="application_form_container" <?php echo ( $is_pending_affiliate ) ? '' : 'style="display: none"' ?>>
165
+ <h3><?php fs_esc_html_echo_inline( 'Affiliate', 'affiliate', $slug ) ?></h3>
166
+ <form>
167
+ <div class="input-container input-container-text">
168
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'Email address', 'email-address', $slug ) ?></label>
169
+ <input id="email_address" type="text" value="<?php echo esc_attr( $email_address ) ?>" class="regular-text" <?php echo ( $readonly || is_object( $user ) ) ? 'readonly' : '' ?>>
170
+ </div>
171
+ <div class="input-container input-container-text">
172
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'Full name', 'full-name', $slug ) ?></label>
173
+ <input id="full_name" type="text" value="<?php echo esc_attr( $full_name ) ?>" class="regular-text" <?php echo $readonly ?>>
174
+ </div>
175
+ <div class="input-container input-container-text">
176
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'PayPal account email address', 'paypal-account-email-address', $slug ) ?></label>
177
+ <input id="paypal_email" type="text" value="<?php echo esc_attr( $paypal_email_address ) ?>" class="regular-text" <?php echo $readonly ?>>
178
+ </div>
179
+ <div class="input-container input-container-text">
180
+ <label class="input-label"><?php echo esc_html( sprintf( fs_text_inline( 'Where are you going to promote the %s?', 'domain-field-label', $slug ), $module_type ) ) ?></label>
181
+ <input id="domain" type="text" value="<?php echo esc_attr( $domain ) ?>" class="domain regular-text" <?php echo $readonly ?>>
182
+ <p class="description"><?php echo esc_html( sprintf( fs_text_inline( 'Enter the domain of your website or other websites from where you plan to promote the %s.', 'domain-field-desc', $slug ), $module_type ) ) ?></p>
183
+ <?php if ( ! $is_affiliate ) : ?>
184
+ <a id="add_domain" href="#" class="disabled">+ <?php fs_esc_html_echo_inline( 'Add another domain', 'add-another-domain', $slug ) ?>...</a>
185
+ <?php endif ?>
186
+ </div>
187
+ <div id="extra_domains_container" class="input-container input-container-text" <?php echo $is_pending_affiliate ? '' : 'style="display: none"' ?>>
188
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'Extra Domains', 'extra-domain-fields-label', $slug ) ?></label>
189
+ <p class="description"><?php fs_esc_html_echo_inline( 'Extra domains where you will be marketing the product from.', 'extra-domain-fields-desc', $slug ) ?></p>
190
+ <?php if ( $is_pending_affiliate && ! empty( $extra_domains ) ) : ?>
191
+ <?php foreach ( $extra_domains as $extra_domain ) : ?>
192
+ <div class="extra-domain-input-container">
193
+ <input type="text" value="<?php echo esc_attr( $extra_domain ) ?>" class="domain regular-text" <?php echo $readonly ?>>
194
+ </div>
195
+ <?php endforeach ?>
196
+ <?php endif ?>
197
+ </div>
198
+ <div class="input-container">
199
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'Promotion methods', 'promotion-methods', $slug ) ?></label>
200
+ <div>
201
+ <input id="promotion_method_social_media" type="checkbox" <?php checked( $promotion_method_social_media ) ?> <?php disabled( $is_affiliate ) ?>/>
202
+ <label for="promotion_method_social_media"><?php fs_esc_html_echo_inline( 'Social media (Facebook, Twitter, etc.)', 'social-media', $slug ) ?></label>
203
+ </div>
204
+ <div>
205
+ <input id="promotion_method_mobile_apps" type="checkbox" <?php checked( $promotion_method_mobile_apps ) ?> <?php disabled( $is_affiliate ) ?>/>
206
+ <label for="promotion_method_mobile_apps"><?php fs_esc_html_echo_inline( 'Mobile apps', 'mobile-apps', $slug ) ?></label>
207
+ </div>
208
+ </div>
209
+ <div class="input-container input-container-text">
210
+ <label class="input-label"><nobr><?php fs_esc_html_echo_inline( 'Website, email, and social media statistics (optional)', 'statistics-information-field-label', $slug ) ?></nobr></label>
211
+ <textarea id="statistics_information" rows="5" <?php echo $readonly ?> class="regular-text"><?php echo $statistics_information ?></textarea>
212
+ <?php if ( ! $is_affiliate ) : ?>
213
+ <p class="description"><?php fs_esc_html_echo_inline( 'Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).', 'statistics-information-field-desc', $slug ) ?></p>
214
+ <?php endif ?>
215
+ </div>
216
+ <div class="input-container input-container-text">
217
+ <label class="input-label"><?php fs_esc_html_echo_inline( 'How will you promote us?', 'promotion-method-desc-field-label', $slug ) ?></label>
218
+ <textarea id="promotion_method_description" rows="5" <?php echo $readonly ?> class="regular-text"><?php echo $promotion_method_description ?></textarea>
219
+ <?php if ( ! $is_affiliate ) : ?>
220
+ <p class="description"><?php echo esc_html( sprintf( fs_text_inline( 'Please provide details on how you intend to promote %s (please be as specific as possible).', 'promotion-method-desc-field-desc', $slug ), $plugin_title ) ) ?></p>
221
+ <?php endif ?>
222
+ </div>
223
+ <?php if ( ! $is_affiliate ) : ?>
224
+ <div>
225
+ <input type="checkbox" id="legal_consent_checkbox">
226
+ <label for="legal_consent_checkbox">I agree to the <a href="<?php echo $affiliate_program_terms_url ?>" target="_blank" rel="noopener">Referrer Program</a>'s terms & conditions.</label>
227
+ </div>
228
+ <?php endif ?>
229
+ </form>
230
+ </div>
231
+ <?php if ( ! $is_affiliate ) : ?>
232
+ <a id="cancel_button" href="#" class="button button-secondary button-cancel" style="display: none"><?php fs_esc_html_echo_inline( 'Cancel', 'cancel', $slug ) ?></a>
233
+ <a id="submit_button" class="button button-primary disabled" href="#" style="display: none"><?php echo esc_html( $apply_to_become_affiliate_text ) ?></a>
234
+ <a id="apply_button" class="button button-primary" href="#"><?php fs_esc_html_echo_inline( 'Become an affiliate', 'become-an-affiliate', $slug ) ?></a>
235
+ <?php endif ?>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </form>
241
+ <script type="text/javascript">
242
+ jQuery(function ($) {
243
+ var
244
+ $contentWrapper = $('#fs_affiliation_content_wrapper'),
245
+ $socialMedia = $('#promotion_method_social_media'),
246
+ $mobileApps = $('#promotion_method_mobile_apps'),
247
+ $applyButton = $('#apply_button'),
248
+ $submitButton = $('#submit_button'),
249
+ $cancelButton = $('#cancel_button'),
250
+ $applicationFormContainer = $('#application_form_container'),
251
+ $errorMessageContainer = $('#error_message'),
252
+ $domain = $('#domain'),
253
+ $addDomain = $('#add_domain'),
254
+ $extraDomainsContainer = $('#extra_domains_container'),
255
+ $legalConsentCheckbox = $( '#legal_consent_checkbox' );
256
+
257
+ $applyButton.click(function (evt) {
258
+ evt.preventDefault();
259
+
260
+ var $this = $(this);
261
+ $this.hide();
262
+
263
+ $applicationFormContainer.show();
264
+ $cancelButton.show();
265
+ $submitButton.show();
266
+
267
+ $contentWrapper.find('input[type="text"]:first').focus();
268
+ });
269
+
270
+ $submitButton.click(function (evt) {
271
+ evt.preventDefault();
272
+
273
+ var $this = $(this);
274
+
275
+ if ($this.hasClass('disabled')) {
276
+ return;
277
+ }
278
+
279
+ $errorMessageContainer.hide();
280
+
281
+ var
282
+ $emailAddress = $('#email_address'),
283
+ emailAddress = null,
284
+ paypalEmailAddress = $('#paypal_email').val().trim();
285
+
286
+ if (1 === $emailAddress.length) {
287
+ emailAddress = $emailAddress.val().trim();
288
+
289
+ if (0 === emailAddress.length) {
290
+ showErrorMessage('<?php fs_esc_js_echo_inline( 'Email address is required.', 'email-address-is-required', $slug ) ?>');
291
+ return;
292
+ }
293
+ }
294
+
295
+ if (0 === paypalEmailAddress.length) {
296
+ showErrorMessage('<?php fs_esc_js_echo_inline( 'PayPal email address is required.', 'paypal-email-address-is-required', $slug ) ?>');
297
+ return;
298
+ }
299
+
300
+ var
301
+ $extraDomains = $extraDomainsContainer.find('.domain'),
302
+ domain = $domain.val().trim().toLowerCase(),
303
+ extraDomains = [];
304
+
305
+ if (0 === domain.length) {
306
+ showErrorMessage('<?php fs_esc_js_echo_inline( 'Domain is required.', 'domain-is-required', $slug ) ?>');
307
+ return;
308
+ } else if ('freemius.com' === domain) {
309
+ showErrorMessage('<?php fs_esc_js_echo_inline( 'Invalid domain', 'invalid-domain', $slug ) ?>' + ' [' + domain + '].');
310
+ return;
311
+ }
312
+
313
+ if ($extraDomains.length > 0) {
314
+ var hasError = false;
315
+
316
+ $extraDomains.each(function () {
317
+ var
318
+ $this = $(this),
319
+ extraDomain = $this.val().trim().toLowerCase();
320
+ if (0 === extraDomain.length || extraDomain === domain) {
321
+ return true;
322
+ } else if ('freemius.com' === extraDomain) {
323
+ showErrorMessage('<?php fs_esc_js_echo_inline( 'Invalid domain', 'invalid-domain', $slug ) ?>' + ' [' + extraDomain + '].');
324
+ hasError = true;
325
+ return false;
326
+ }
327
+
328
+ extraDomains.push(extraDomain);
329
+ });
330
+
331
+ if (hasError) {
332
+ return;
333
+ }
334
+ }
335
+
336
+ var
337
+ promotionMethods = [],
338
+ statisticsInformation = $('#statistics_information').val(),
339
+ promotionMethodDescription = $('#promotion_method_description').val();
340
+
341
+ if ($socialMedia.attr('checked')) {
342
+ promotionMethods.push('social_media');
343
+ }
344
+
345
+ if ($mobileApps.attr('checked')) {
346
+ promotionMethods.push('mobile_apps');
347
+ }
348
+
349
+ var affiliate = {
350
+ full_name : $('#full_name').val().trim(),
351
+ paypal_email : paypalEmailAddress,
352
+ stats_description : statisticsInformation,
353
+ promotion_method_description: promotionMethodDescription
354
+ };
355
+
356
+ if (null !== emailAddress) {
357
+ affiliate.email = emailAddress;
358
+ }
359
+
360
+ affiliate.domain = domain;
361
+ affiliate.additional_domains = extraDomains;
362
+
363
+ if (promotionMethods.length > 0) {
364
+ affiliate.promotion_methods = promotionMethods.join(',');
365
+ }
366
+
367
+ $.ajax({
368
+ url : ajaxurl,
369
+ method : 'POST',
370
+ data : {
371
+ action : '<?php echo $fs->get_ajax_action( 'submit_affiliate_application' ) ?>',
372
+ security : '<?php echo $fs->get_ajax_security( 'submit_affiliate_application' ) ?>',
373
+ module_id: '<?php echo $module_id ?>',
374
+ affiliate: affiliate
375
+ },
376
+ beforeSend: function () {
377
+ $cancelButton.addClass('disabled');
378
+ $submitButton.addClass('disabled');
379
+ $submitButton.text('<?php fs_esc_js_echo_inline( 'Submitting', 'submitting' ) ?>...');
380
+ },
381
+ success : function (result) {
382
+ if (result.success) {
383
+ location.reload();
384
+ } else {
385
+ if (result.error && result.error.length > 0) {
386
+ showErrorMessage(result.error);
387
+ }
388
+
389
+ $cancelButton.removeClass('disabled');
390
+ $submitButton.removeClass('disabled');
391
+ $submitButton.text('<?php echo esc_js( $apply_to_become_affiliate_text ) ?>')
392
+ }
393
+ }
394
+ });
395
+ });
396
+
397
+ $cancelButton.click(function (evt) {
398
+ evt.preventDefault();
399
+
400
+ var $this = $(this);
401
+
402
+ if ($this.hasClass('disabled')) {
403
+ return;
404
+ }
405
+
406
+ $applicationFormContainer.hide();
407
+ $this.hide();
408
+ $submitButton.hide();
409
+
410
+ $applyButton.show();
411
+
412
+ window.scrollTo(0, 0);
413
+ });
414
+
415
+ $domain.on('input propertychange', onDomainChange);
416
+
417
+ $addDomain.click(function (evt) {
418
+ evt.preventDefault();
419
+
420
+ var
421
+ $this = $(this),
422
+ domain = $domain.val().trim();
423
+
424
+ if ($this.hasClass('disabled') || 0 === domain.length) {
425
+ return;
426
+ }
427
+
428
+ $domain.off('input propertychange');
429
+ $this.addClass('disabled');
430
+
431
+ var
432
+ $extraDomainInputContainer = $('<div class="extra-domain-input-container"><input type="text" class="domain regular-text"/></div>'),
433
+ $extraDomainInput = $extraDomainInputContainer.find('input'),
434
+ $removeDomain = $('<a href="#" class="remove-domain"><i class="dashicons dashicons-no" title="<?php fs_esc_js_echo_inline( 'Remove', 'remove', $slug ) ?>"></i></a>');
435
+
436
+ $extraDomainInputContainer.append($removeDomain);
437
+
438
+ $extraDomainInput.on('input propertychange', onDomainChange);
439
+
440
+ $removeDomain.click(function (evt) {
441
+ evt.preventDefault();
442
+
443
+ var
444
+ $extraDomainInputs = $('.extra-domain-input-container .domain');
445
+
446
+ if (1 === $extraDomainInputs.length)
447
+ $extraDomainInputs.val('').focus();
448
+ else
449
+ $(this).parent().remove();
450
+ });
451
+
452
+ $extraDomainsContainer.show();
453
+
454
+ $extraDomainInputContainer.appendTo($extraDomainsContainer);
455
+ $extraDomainInput.focus();
456
+
457
+ $this.appendTo($extraDomainsContainer);
458
+ });
459
+
460
+ /**
461
+ * @author Leo Fajardo (@leorw)
462
+ */
463
+ function onDomainChange() {
464
+ var
465
+ domain = $(this).val().trim();
466
+
467
+ if (domain.length > 0) {
468
+ $addDomain.removeClass('disabled');
469
+ } else {
470
+ $addDomain.addClass('disabled');
471
+ }
472
+ }
473
+
474
+ /**
475
+ * @author Leo Fajardo (@leorw)
476
+ *
477
+ * @param {String} message
478
+ */
479
+ function showErrorMessage(message) {
480
+ $errorMessageContainer.find('strong').text(message);
481
+ $errorMessageContainer.show();
482
+
483
+ window.scrollTo(0, 0);
484
+ }
485
+
486
+ /**
487
+ * @author Xiaheng Chen (@xhchen)
488
+ *
489
+ * @since 2.4.0
490
+ */
491
+ $legalConsentCheckbox.click( function () {
492
+ if ( $( this ).prop( 'checked' ) ) {
493
+ $submitButton.removeClass( 'disabled' );
494
+ } else {
495
+ $submitButton.addClass( 'disabled' );
496
+ }
497
+ } );
498
+ });
499
+ </script>
500
+ </div>
501
+ <?php
502
+ $params = array(
503
+ 'page' => 'affiliation',
504
+ 'module_id' => $module_id,
505
+ 'module_slug' => $slug,
506
+ 'module_version' => $fs->get_plugin_version(),
507
+ );
508
+ fs_require_template( 'powered-by.php', $params );
509
  ?>
freemius/templates/forms/license-activation.php CHANGED
@@ -115,13 +115,15 @@ HTML;
115
  * @var FS_Plugin_License $license
116
  */
117
  foreach ( $available_licenses as $license ) {
 
 
118
  $label = sprintf(
119
  "%s-Site %s License - %s",
120
  ( 1 == $license->quota ?
121
  'Single' :
122
  ( $license->is_unlimited() ? 'Unlimited' : $license->quota )
123
  ),
124
- $fs->_get_plan_by_id( $license->plan_id )->title,
125
  $license->get_html_escaped_masked_secret_key()
126
  );
127
 
115
  * @var FS_Plugin_License $license
116
  */
117
  foreach ( $available_licenses as $license ) {
118
+ $plan = $fs->_get_plan_by_id( $license->plan_id );
119
+
120
  $label = sprintf(
121
  "%s-Site %s License - %s",
122
  ( 1 == $license->quota ?
123
  'Single' :
124
  ( $license->is_unlimited() ? 'Unlimited' : $license->quota )
125
  ),
126
+ ( is_object( $plan ) ? $plan->title : '' ),
127
  $license->get_html_escaped_masked_secret_key()
128
  );
129
 
gutenberg/src/block/index.js CHANGED
@@ -29,7 +29,7 @@ registerBlockType( 'fooplugins/foogallery', {
29
  title: __( 'FooGallery' ), // Block title.
30
  description: __( 'Insert a FooGallery into your content' ),
31
  icon: 'format-gallery', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
32
- category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
33
  keywords: [
34
  __( 'foogallery' ),
35
  __( 'gallery' ),
29
  title: __( 'FooGallery' ), // Block title.
30
  description: __( 'Insert a FooGallery into your content' ),
31
  icon: 'format-gallery', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
32
+ category: 'media', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
33
  keywords: [
34
  __( 'foogallery' ),
35
  __( 'gallery' ),
includes/WPThumb/wpthumb.background-fill.php DELETED
@@ -1,146 +0,0 @@
1
- <?php
2
-
3
- class WP_Thumb_Background_Fill {
4
-
5
- private $args = array();
6
- private $editor;
7
-
8
- public function __construct( $editor, $args ) {
9
-
10
- $this->editor = $editor;
11
-
12
- $defaults = array(
13
- 'background_fill' => false,
14
- );
15
-
16
- $this->args = wp_parse_args( $args, $defaults );
17
-
18
- if ( $this->args['background_fill'] && $this->args['background_fill'] !== 'auto' ) {
19
-
20
- $this->fill_with_color( $this->args['background_fill'] );
21
- } else if ( $this->args['background_fill'] && $this->args['background_fill'] === 'auto' ) {
22
-
23
- if ( $color = $this->get_background_color() ) {
24
- $this->fill_with_color( $color );
25
- }
26
- }
27
- }
28
-
29
- /**
30
- * Background fill an image using the provided color
31
- */
32
- public function fill_with_color( $color ) {
33
-
34
- if ( ! is_array( $color ) && strlen( $color ) == 3 ) {
35
- $color = (float) str_pad( (string) $color, 9, $color ) . '000';
36
- }
37
-
38
- if ( ! is_array( $color ) ) {
39
- $color = array( 'top' => $color, 'bottom' => $color, 'left' => $color, 'right' => $color );
40
- }
41
-
42
- $this->fill_color( $color );
43
-
44
- }
45
-
46
- /**
47
- * Background fill an image using the provided color
48
- *
49
- * @param int $width The desired width of the new image
50
- * @param int $height The desired height of the new image
51
- * @param Array $colors The desired pad colors in RGB format, array should be array( 'top' => '', 'right' => '', 'bottom' => '', 'left' => '' );
52
- */
53
- private function fill_color( array $colors ) {
54
-
55
- $current_size = $this->editor->get_size();
56
-
57
- $size = array( 'width' => $this->args['width'], 'height' => $this->args['height'] );
58
-
59
- $offsetLeft = ( $size['width'] - $current_size['width'] ) / 2;
60
- $offsetTop = ( $size['height'] - $current_size['height'] ) / 2;
61
-
62
- $new_image = imagecreatetruecolor( $size['width'], $size['height'] );
63
-
64
- // This is needed to support alpha
65
- imagesavealpha( $new_image, true );
66
- imagealphablending( $new_image, false );
67
-
68
- // Check if we are padding vertically or horizontally
69
- if ( $current_size['width'] != $size['width'] ) {
70
-
71
- $colorToPaint = imagecolorallocatealpha( $new_image, substr( $colors['left'], 0, 3 ), substr( $colors['left'], 3, 3 ), substr( $colors['left'], 6, 3 ), substr( $colors['left'], 9, 3 ) );
72
-
73
- // Fill left color
74
- imagefilledrectangle( $new_image, 0, 0, $offsetLeft + 5, $size['height'], $colorToPaint );
75
-
76
- $colorToPaint = imagecolorallocatealpha( $new_image, substr( $colors['right'], 0, 3 ), substr( $colors['right'], 3, 3 ), substr( $colors['right'], 6, 3 ), substr( $colors['left'], 9, 3 ) );
77
-
78
- // Fill right color
79
- imagefilledrectangle( $new_image, $offsetLeft + $current_size['width'] - 5, 0, $size['width'], $size['height'], $colorToPaint );
80
-
81
- }
82
-
83
- if ( $current_size['height'] != $size['height'] ) {
84
-
85
- $colorToPaint = imagecolorallocatealpha( $new_image, substr( $colors['top'], 0, 3 ), substr( $colors['top'], 3, 3 ), substr( $colors['top'], 6, 3 ), substr( $colors['left'], 9, 3 ) );
86
-
87
- // Fill top color
88
- imagefilledrectangle( $new_image, 0, 0, $size['width'], $offsetTop + 5, $colorToPaint );
89
-
90
- $colorToPaint = imagecolorallocatealpha( $new_image, substr( $colors['bottom'], 0, 3 ), substr( $colors['bottom'], 3, 3 ), substr( $colors['bottom'], 6, 3 ), substr( $colors['left'], 9, 3 ) );
91
-
92
- // Fill bottom color
93
- imagefilledrectangle( $new_image, 0, $offsetTop - 5 + $current_size['height'], $size['width'], $size['height'], $colorToPaint );
94
-
95
- }
96
-
97
- imagecopy( $new_image, $this->editor->get_image(), $offsetLeft, $offsetTop, 0, 0, $current_size['width'], $current_size['height'] );
98
-
99
- $this->editor->update_image( $new_image );
100
- $this->editor->update_size();
101
- }
102
-
103
- public function get_background_color() {
104
-
105
- $current_size = $this->editor->get_size();
106
-
107
- $coords = array(
108
- array( 0, 0 ),
109
- array( $current_size['width'] - 1, 0 ),
110
- array( $current_size['width'] - 1, $current_size['height'] - 1 ),
111
- array( 0, $current_size['height'] - 1 ),
112
- );
113
-
114
- $colors = array();
115
- $color = 0;
116
-
117
- foreach ( $coords as $coord ) {
118
- $rgb = imagecolorat( $this->editor->get_image(), $coord[0], $coord[1] );
119
- $c = imagecolorsforindex( $this->editor->get_image(), $rgb );
120
-
121
- $colors[] = $c['red'] + $c['green'] + $c['blue'] + $c['alpha'];
122
- $color = str_pad( $c['red'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['green'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['blue'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['alpha'], 3, '0', STR_PAD_LEFT );
123
- }
124
-
125
- if ( max( $colors ) > min( $colors ) + 15 ) {
126
- return false;
127
- }
128
-
129
- return $color;
130
-
131
- }
132
-
133
- }
134
-
135
- function wpthumb_background_fill( $editor, $args ) {
136
-
137
- // currently only supports GD
138
- if ( ! is_a( $editor, 'WP_Thumb_Image_Editor_GD' ) ) {
139
- return $editor;
140
- }
141
-
142
- $bg = new WP_Thumb_Background_Fill( $editor, $args );
143
-
144
- return $editor;
145
- }
146
- add_filter( 'wpthumb_image_post', 'wpthumb_background_fill', 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/WPThumb/wpthumb.crop-from-position.php DELETED
@@ -1,85 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Only add the watermarking admin options if the current theme supports it, as we don't want to clutter
5
- * for people who don't care
6
- *
7
- */
8
- function wpthumb_add_crop_from_position_admin_hooks() {
9
- add_filter( 'attachment_fields_to_edit', 'wpthumb_media_form_crop_position', 10, 2 );
10
- add_filter( 'attachment_fields_to_save', 'wpthumb_media_form_crop_position_save', 10, 2 );
11
- }
12
- add_action( 'init', 'wpthumb_add_crop_from_position_admin_hooks' );
13
-
14
- /**
15
- * wpthumb_media_form_crop_position function.
16
- *
17
- * Adds a back end for selecting the crop position of images.
18
- *
19
- * @access public
20
- *
21
- * @param array $fields
22
- * @param array $post
23
- * @return $post
24
- */
25
- function wpthumb_media_form_crop_position( $fields, $post ) {
26
-
27
- if ( ! wp_attachment_is_image( $post->ID ) ) {
28
- return $fields;
29
- }
30
-
31
- $current_position = get_post_meta( $post->ID, 'wpthumb_crop_pos', true );
32
-
33
- if ( ! $current_position ) {
34
- $current_position = wpthumb_default_crop_position();
35
- }
36
-
37
- $html = '<style>#wpthumb_crop_pos { padding: 5px; } #wpthumb_crop_pos input { margin: 5px; width: auto; }</style>';
38
- $html .= '<div id="wpthumb_crop_pos">';
39
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="left,top" title="Left, Top" ' . checked( 'left,top', $current_position, false ) . '/>';
40
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="center,top" title="Center, Top" ' . checked( 'center,top', $current_position, false ) . '/>';
41
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="right,top" title="Right, Top" ' . checked( 'right,top', $current_position, false ) . '/><br/>';
42
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="left,center" title="Left, Center" ' . checked( 'left,center', $current_position, false ) . '/>';
43
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="center,center" title="Center, Center"' . checked( 'center,center', $current_position, false ) . '/>';
44
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="right,center" title="Right, Center" ' . checked( 'right,center', $current_position, false ) . '/><br/>';
45
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="left,bottom" title="Left, Bottom" ' . checked( 'left,bottom', $current_position, false ) . '/>';
46
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="center,bottom" title="Center, Bottom" ' . checked( 'center,bottom', $current_position, false ) . '/>';
47
- $html .= '<input type="radio" name="attachments[' . $post->ID . '][wpthumb_crop_pos]" value="right,bottom" title="Right, Bottom" ' . checked( 'right,bottom', $current_position, false ) . '/>';
48
- $html .= '</div>';
49
-
50
- $fields['crop-from-position'] = array(
51
- 'label' => __( 'Crop Position', 'wpthumb' ),
52
- 'input' => 'html',
53
- 'html' => $html
54
- );
55
-
56
- return $fields;
57
-
58
- }
59
-
60
- /**
61
- * wpthumb_media_form_crop_position_save function.
62
- *
63
- * Saves crop position in post meta.
64
- *
65
- * @access public
66
- *
67
- * @param array $post
68
- * @param array $attachment
69
- * @return $post
70
- */
71
- function wpthumb_media_form_crop_position_save( $post, $attachment ) {
72
-
73
- if ( ! isset( $attachment['wpthumb_crop_pos'] ) ) {
74
- return $post;
75
- }
76
-
77
- if ( $attachment['wpthumb_crop_pos'] == wpthumb_default_crop_position() ) {
78
- delete_post_meta( $post['ID'], 'wpthumb_crop_pos' );
79
- } else {
80
- update_post_meta( $post['ID'], 'wpthumb_crop_pos', $attachment['wpthumb_crop_pos'] );
81
- }
82
-
83
- return $post;
84
-
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/WPThumb/wpthumb.image-editor.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
-
3
- class WP_Thumb_Image_Editor_GD extends WP_Image_Editor_GD {
4
-
5
- public function get_image() {
6
- return $this->image;
7
- }
8
-
9
- public function update_image( $image ) {
10
- $this->image = $image;
11
- }
12
-
13
- public function update_size( $width = null, $height = null ) {
14
- return parent::update_size( $width, $height );
15
- }
16
-
17
- public static function supports_mime_type( $mime_type ) {
18
- $image_types = imagetypes();
19
- switch( $mime_type ) {
20
- case 'image/jpeg':
21
- case 'image/jpg':
22
- return ($image_types & IMG_JPG) != 0;
23
- case 'image/png':
24
- return ($image_types & IMG_PNG) != 0;
25
- case 'image/gif':
26
- return ($image_types & IMG_GIF) != 0;
27
- }
28
-
29
- return false;
30
- }
31
- }
32
-
33
- class WP_Thumb_Image_Editor_Imagick extends WP_Image_Editor_Imagick {
34
-
35
- public function get_image() {
36
- return $this->image;
37
- }
38
-
39
- public function update_image( $image ) {
40
- $this->image = $image;
41
- }
42
-
43
- public function update_size( $width = null, $height = null ) {
44
- return parent::update_size( $width, $height );
45
- }
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/WPThumb/wpthumb.php DELETED
@@ -1,836 +0,0 @@
1
- <?php
2
- /*
3
- Plugin Name: WP Thumb
4
- Plugin URI: https://github.com/humanmade/WPThumb
5
- Description: An on-demand image generation replacement for WordPress' image resizing.
6
- Author: Human Made Limited
7
- Version: 0.10
8
- Author URI: https://www.hmn.md/
9
- */
10
-
11
- /* Copyright 2014 Human Made Limited (email : hello@humanmade.co.uk)
12
-
13
- This program is free software; you can redistribute it and/or modify
14
- it under the terms of the GNU General Public License as published by
15
- the Free Software Foundation; either version 2 of the License, or
16
- (at your option) any later version.
17
-
18
- This program is distributed in the hope that it will be useful,
19
- but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
- GNU General Public License for more details.
22
-
23
- You should have received a copy of the GNU General Public License
24
- along with this program; if not, write to the Free Software
25
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
- */
27
-
28
- define( 'WP_THUMB_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
29
- define( 'WP_THUMB_URL', plugin_dir_url( __FILE__ ) );
30
-
31
- // TODO wpthumb_create_args_from_size filter can pass string or array which makes it difficult to hook into
32
-
33
-
34
- // Load the watermarking class
35
- include_once( WP_THUMB_PATH . '/wpthumb.watermark.php' );
36
- include_once( WP_THUMB_PATH . '/wpthumb.background-fill.php' );
37
- include_once( WP_THUMB_PATH . '/wpthumb.crop-from-position.php' );
38
- include_once( WP_THUMB_PATH . '/wpthumb.shortcodes.php' );
39
-
40
- /**
41
- * Base WP_Thumb class
42
- *
43
- */
44
- class WP_Thumb {
45
-
46
- /**
47
- * Array of image args
48
- *
49
- * @var array
50
- * @access private
51
- */
52
- private $args;
53
-
54
- /**
55
- * The file path the original image
56
- *
57
- * @var string
58
- * @access private
59
- */
60
- private $file_path;
61
-
62
- private static $wp_upload_dir;
63
-
64
- private static function uploadDir() {
65
-
66
- if ( empty( self::$wp_upload_dir ) ) {
67
- self::$wp_upload_dir = wp_upload_dir();
68
- }
69
-
70
- // if blogs are ever switched we need to clear the cache
71
- add_action( 'switch_blog', array( 'WP_Thumb', 'clearUploadDirCache' ) );
72
-
73
- return self::$wp_upload_dir;
74
- }
75
-
76
- /**
77
- * Clear the internally cached upload dir. WP Thumb cached the results of wp_upload_dir()
78
- * for performance, however it's sometimes necessary to clear the internal cache, such as switching
79
- * blogs in multisite
80
- */
81
- public static function clearUploadDirCache() {
82
- self::$wp_upload_dir = null;
83
- }
84
-
85
- private static function get_home_path() {
86
- return str_replace( str_replace( home_url(), '', site_url() ), '', ABSPATH );
87
- }
88
-
89
- /**
90
- * Setup phpthumb, parse the args and generate the cache file
91
- *
92
- * @access public
93
- *
94
- * @param string $file_path . (default: null)
95
- * @param array $args . (default: array())
96
- */
97
- public function __construct( $file_path = null, $args = array() ) {
98
-
99
- if ( $file_path ) {
100
- $this->setFilePath( $file_path );
101
- }
102
-
103
- if ( $args ) {
104
- $this->setArgs( $args );
105
- }
106
-
107
- if ( $this->getFilePath() && ! $this->errored() ) {
108
-
109
- if ( ! file_exists( $this->getCacheFilePath() ) || ! $this->args['cache'] ) {
110
-
111
- $this->generateCacheFile();
112
- }
113
- }
114
-
115
- }
116
-
117
- /**
118
- * Set the file path of the original image
119
- *
120
- * Will convert URLS to paths.
121
- *
122
- * @param string $file_path
123
- */
124
- public function setFilePath( $file_path ) {
125
-
126
- $upload_dir = self::uploadDir();
127
- $this->_file_path = null;
128
-
129
- if ( strpos( $file_path, self::get_home_path() ) === 0 ) {
130
- $this->file_path = $file_path;
131
-
132
- return;
133
- }
134
-
135
- $base_url = set_url_scheme( $upload_dir['baseurl'] );
136
-
137
- // If it's an uploaded file
138
- if ( strpos( $file_path, $base_url ) !== false ) {
139
- $this->file_path = str_replace( $base_url, $upload_dir['basedir'], $file_path );
140
- } else {
141
- $this->file_path = str_replace( trailingslashit( home_url() ), self::get_home_path(), $file_path );
142
- }
143
-
144
- // if it's a local path, lets check it now
145
- if ( strpos( $this->file_path, '/' ) === 0 && strpos( $this->file_path, '//' ) !== 0 && ! file_exists( $this->file_path ) ) {
146
- $this->error = new WP_Error( 'file-not-found' );
147
- }
148
- }
149
-
150
- /**
151
- * Parse the args and merge with defaults
152
- *
153
- * @param array $args
154
- */
155
- public function setArgs( $args ) {
156
-
157
- $arg_defaults = array(
158
- 'width' => 0,
159
- 'height' => 0,
160
- 'crop' => false,
161
- 'crop_from_position' => wpthumb_default_crop_position(),
162
- 'resize' => true,
163
- 'watermark_options' => array(),
164
- 'cache' => true,
165
- 'skip_remote_check' => false,
166
- 'default' => null,
167
- 'jpeg_quality' => 90,
168
- 'resize_animations' => true,
169
- 'return' => 'url',
170
- 'custom' => false,
171
- 'background_fill' => null,
172
- 'output_file' => false,
173
- 'cache_with_query_params' => false
174
- );
175
-
176
- $args = wp_parse_args( $args, $arg_defaults );
177
- $new_args = array();
178
-
179
- if ( $args['width'] === 'thumbnail' ) {
180
- $new_args = array(
181
- 'width' => get_option( 'thumbnail_size_w' ),
182
- 'height' => get_option( 'thumbnail_size_h' ),
183
- 'crop' => get_option( 'thumbnail_crop' )
184
- );
185
- } elseif ( $args['width'] === 'medium' ) {
186
- $new_args = array( 'width' => get_option( 'medium_size_w' ), 'height' => get_option( 'medium_size_h' ) );
187
- } elseif ( $args['width'] === 'large' ) {
188
- $new_args = array( 'width' => get_option( 'large_size_w' ), 'height' => get_option( 'large_size_h' ) );
189
- } elseif ( is_string( $args['width'] ) && $args['width'] ) {
190
- $new_args = apply_filters( 'wpthumb_create_args_from_size', $args );
191
- } elseif ( is_array( $args['width'] ) ) {
192
- $new_args = $args;
193
- }
194
-
195
- $args = wp_parse_args( $new_args, $args );
196
-
197
- // Cast some args
198
- $args['crop'] = (bool) $args['crop'];
199
- $args['resize'] = (bool) $args['resize'];
200
- $args['cache'] = (bool) $args['cache'];
201
- $args['width'] = (int) $args['width'];
202
- $args['height'] = (int) $args['height'];
203
-
204
- // Format the crop from position arg
205
- if ( is_string( $args['crop_from_position'] ) && $args['crop_from_position'] ) {
206
- $args['crop_from_position'] = explode( ',', $args['crop_from_position'] );
207
- }
208
-
209
- $this->args = $args;
210
-
211
- }
212
-
213
- /**
214
- * Return the file path to the original image
215
- *
216
- * @return string
217
- */
218
- public function getFilePath() {
219
-
220
- if ( ! empty( $this->_file_path ) ) {
221
- return $this->_file_path;
222
- }
223
-
224
- if ( strpos( $this->file_path, '/' ) === 0 && ! file_exists( $this->file_path ) && $this->args['default'] ) {
225
- $this->file_path = $this->args['default'];
226
- } elseif ( ( ! $this->file_path ) && $this->args['default'] && file_exists( $this->args['default'] ) ) {
227
- $this->file_path = $this->args['default'];
228
- }
229
-
230
- //added this filter to allow a fallback to legacy logic if needed
231
- if ( true === apply_filters( 'foogallery_wpthumb_legacy_logic', false ) ) {
232
- if ( $this->getArg( 'cache_with_query_params' ) ) {
233
- return $this->file_path;
234
- }
235
-
236
- $path_bits = explode( '?', $this->file_path );
237
- $this->_file_path = reset( $path_bits );
238
-
239
- return $this->_file_path;
240
- }
241
-
242
- return $this->file_path;
243
- }
244
-
245
- /**
246
- * Return the array of args
247
- *
248
- * @return array
249
- */
250
- public function getArgs() {
251
- return (array) $this->args;
252
- }
253
-
254
- /**
255
- * Get a specific arg
256
- *
257
- * @access public
258
- *
259
- * @param string $arg
260
- * @return mixed
261
- */
262
- public function getArg( $arg ) {
263
-
264
- if ( isset( $this->args[ $arg ] ) ) {
265
- return $this->args[ $arg ];
266
- }
267
-
268
- return false;
269
-
270
- }
271
-
272
- /**
273
- * Get the extension of the original image
274
- *
275
- * @return string
276
- */
277
- public function getFileExtension() {
278
-
279
- $filename = parse_url( $this->getFilePath(), PHP_URL_PATH );
280
-
281
- $ext = pathinfo( $filename, PATHINFO_EXTENSION );
282
-
283
- if ( ! $ext ) {
284
- // Seems like we dont have an ext, lets guess at JPG
285
- $ext = 'jpg';
286
- }
287
-
288
- return strtolower( $ext );
289
- }
290
-
291
- /**
292
- * Get the filepath to the cache file
293
- *
294
- * @access public
295
- * @return string
296
- */
297
- public function getCacheFilePath() {
298
-
299
- $path = $this->getFilePath();
300
-
301
- if ( ! $path ) {
302
- return '';
303
- }
304
-
305
- return apply_filters( 'wpthumb_cache_file_path', trailingslashit( $this->getCacheFileDirectory() ) . $this->getCacheFileName(), $this );
306
-
307
- }
308
-
309
- /**
310
- * Get the directory that the cache file should be saved too
311
- *
312
- * @return string
313
- */
314
- public function getCacheFileDirectory() {
315
-
316
- if ( $this->getArg( 'output_file' ) ) {
317
- return dirname( $this->getArg( 'output_file' ) );
318
- }
319
-
320
- $path = $this->getFilePath();
321
-
322
- if ( ! $path ) {
323
- return '';
324
- }
325
-
326
- $original_filename = basename( $path );
327
-
328
- // TODO use pathinfo
329
- $parts = explode( '.', $original_filename );
330
-
331
- array_pop( $parts );
332
-
333
- $filename_nice = implode( '_', $parts );
334
-
335
- $upload_dir = self::uploadDir();
336
-
337
- if ( strpos( $path, $upload_dir['basedir'] ) === 0 ) :
338
-
339
- $subdir = dirname( str_replace( $upload_dir['basedir'], '', $path ) );
340
- $new_dir = $upload_dir['basedir'] . '/cache' . trailingslashit( $subdir ) . $filename_nice;
341
-
342
- elseif ( strpos( $path, WP_CONTENT_DIR ) === 0 ) :
343
-
344
- $subdir = dirname( str_replace( WP_CONTENT_DIR, '', $path ) );
345
- $new_dir = $upload_dir['basedir'] . '/cache' . trailingslashit( $subdir ) . $filename_nice;
346
-
347
- elseif ( strpos( $path, self::get_home_path() ) === 0 ) :
348
- $new_dir = $upload_dir['basedir'] . '/cache/local';
349
-
350
- else :
351
-
352
- $parts = parse_url( $path );
353
-
354
- if ( ! empty( $parts['host'] ) )
355
- $new_dir = $upload_dir['basedir'] . '/cache/remote/' . sanitize_title( $parts['host'] );
356
-
357
- else
358
- $new_dir = $upload_dir['basedir'] . '/cache/remote';
359
-
360
- endif;
361
-
362
- // TODO unit test for whether this is needed or not
363
- $new_dir = str_replace( '/cache/cache', '/cache', $new_dir );
364
-
365
- return $new_dir;
366
- }
367
-
368
- /**
369
- * Get the filename of the cache file
370
- *
371
- * @return string
372
- */
373
- public function getCacheFileName() {
374
-
375
- if ( $this->getArg( 'output_file' ) )
376
- return basename( $this->getArg( 'output_file' ) );
377
-
378
- $path = $this->getFilePath();
379
-
380
- if ( ! $path )
381
- return '';
382
-
383
- // Generate a short unique filename
384
- $serialize = crc32( serialize( array_merge( $this->getArgs(), array( $this->getFilePath() ) ) ) );
385
-
386
- // Gifs are converted to pngs
387
- if ( $this->getFileExtension() == 'gif' )
388
- return $serialize . '.png';
389
-
390
- return $serialize . '.' . $this->getFileExtension();
391
-
392
- }
393
-
394
- public function isRemote() {
395
-
396
- return strpos( $this->getFilePath(), self::get_home_path() ) !== 0;
397
-
398
- }
399
-
400
- /**
401
- * Generate the new cache file using the original image and args
402
- *
403
- * @return string new filepath
404
- */
405
- public function generateCacheFile() {
406
-
407
- $new_filepath = $this->getCacheFilePath();
408
- $file_path = $this->getFilePath();
409
-
410
- // Up the php memory limit
411
- @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', '256M' ) );
412
-
413
- // Create the image
414
- $editor = wp_get_image_editor( $file_path, array( 'methods' => array( 'get_image' ) ) );
415
-
416
- /**
417
- * Workaround to preserve image blending when images are not specifically resized (smaller than dimensions for example)
418
- */
419
- if ( is_a( $editor, 'WP_Thumb_Image_Editor_GD' ) ) {
420
- imagealphablending( $editor->get_image(), false );
421
- imagesavealpha( $editor->get_image(), true );
422
- }
423
-
424
- if ( is_wp_error( $editor ) ) {
425
- $this->error = $editor;
426
-
427
- return $this->returnImage();
428
- }
429
-
430
- wp_mkdir_p( $this->getCacheFileDirectory() );
431
-
432
- // Convert gif images to png before resizing
433
- if ( $this->getFileExtension() == 'gif' ) :
434
-
435
- // Save the converted image
436
- $editor->save( $new_filepath, 'image/png' );
437
-
438
- // Pass the new file back through the function so they are resized
439
- return new WP_Thumb( $new_filepath, array_merge( $this->args, array(
440
- 'output_file' => $new_filepath,
441
- 'cache' => false
442
- ) ) );
443
-
444
- endif;
445
-
446
- // Apply JPEG quality settings args
447
- $editor->set_quality( $this->args['jpeg_quality'] );
448
-
449
- apply_filters( 'wpthumb_image_pre', $editor, $this->args );
450
-
451
- if (is_array($this->args)) extract( $this->args );
452
-
453
- // Cropping
454
- if ( $crop && $crop_from_position && $crop_from_position !== array( 'center', 'center' ) ) :
455
-
456
- $this->crop_from_position( $editor, $width, $height, $crop_from_position, $resize );
457
-
458
- elseif ( $crop === true && $resize === true ) :
459
-
460
- $editor->resize( $width, $height, true );
461
-
462
- elseif ( $crop === true && $resize === false ) :
463
- $this->crop_from_center( $editor, $width, $height );
464
-
465
- else :
466
-
467
- $editor->resize( $width, $height );
468
- endif;
469
-
470
- apply_filters( 'wpthumb_image_post', $editor, $this->args );
471
-
472
- $editor->save( $new_filepath );
473
-
474
- do_action( 'wpthumb_saved_cache_image', $this );
475
- }
476
-
477
- private function crop_from_center( $editor, $width, $height ) {
478
-
479
- $size = $editor->get_size();
480
-
481
- $crop = array( 'x' => 0, 'y' => 0, 'width' => $size['width'], 'height' => $size['height'] );
482
-
483
- if ( $width < $size['width'] ) {
484
- $crop['x'] = intval( ( $size['width'] - $width ) / 2 );
485
- $crop['width'] = $width;
486
- }
487
-
488
- if ( $height < $size['height'] ) {
489
- $crop['y'] = intval( ( $size['height'] - $height ) / 2 );
490
- $crop['height'] = $height;
491
- }
492
-
493
- return $editor->crop( $crop['x'], $crop['y'], $crop['width'], $crop['height'] );
494
- }
495
-
496
- private function crop_from_position( $editor, $width, $height, $position, $resize = true ) {
497
-
498
- $size = $editor->get_size();
499
-
500
- // resize to the largest dimension
501
- if ( $resize ) {
502
-
503
- $ratio1 = $size['width'] / $size['height'];
504
- $ratio2 = $width / $height;
505
-
506
- if ( $ratio1 < $ratio2 ) {
507
- $_width = $width;
508
- $_height = $width / $ratio1;
509
- } else {
510
- $_height = $height;
511
- $_width = $height * $ratio1;
512
- }
513
-
514
- $editor->resize( $_width, $_height );
515
- }
516
-
517
- $size = $editor->get_size();
518
- $crop = array( 'x' => 0, 'y' => 0 );
519
-
520
- if ( $position[0] == 'right' )
521
- $crop['x'] = absint( $size['width'] - $width );
522
- else if ( $position[0] == 'center' )
523
- $crop['x'] = intval( absint( $size['width'] - $width ) / 2 );
524
-
525
- if ( $position[1] == 'bottom' )
526
- $crop['y'] = absint( $size['height'] - $height );
527
- else if ( $position[1] == 'center' )
528
- $crop['y'] = intval( absint( $size['height'] - $height ) / 2 );
529
-
530
-
531
- return $editor->crop( $crop['x'], $crop['y'], $width, $height );
532
- }
533
-
534
- /**
535
- * Is there an error
536
- *
537
- * @access public
538
- * @return null
539
- */
540
- public function errored() {
541
- return ! empty( $this->error );
542
- }
543
-
544
- /**
545
- * Returns the error
546
- *
547
- * @access public
548
- * @return null
549
- */
550
- public function error() {
551
- return empty( $this->error ) ? null : $this->error;
552
- }
553
-
554
- /**
555
- * Return the finished image
556
- *
557
- * If there was an error, return the original
558
- *
559
- * @access public
560
- * @return null
561
- */
562
- public function returnImage() {
563
-
564
- if ( $this->errored() ) {
565
-
566
- $path = $this->getFilePath();
567
-
568
- } else {
569
-
570
- $path = $this->getCacheFilePath();
571
- }
572
-
573
- if ( isset( $this->args ) && $this->args['return'] == 'path' )
574
- return $path;
575
-
576
- return $path ? $this->getFileURLForFilePath( $path ) : $path;
577
- }
578
-
579
- /**
580
- * Get the url for the cache file
581
- *
582
- * @return string
583
- */
584
- public function getCacheFileURL() {
585
- return $this->getFileURLForFilePath( $this->getCacheFilePath() );
586
- }
587
-
588
- /**
589
- * Get the url for the original file
590
- *
591
- * @access public
592
- * @return null
593
- */
594
- public function getFileURL() {
595
- return $this->getFileURLForFilePath( $this->getFilePath() );
596
- }
597
-
598
- /**
599
- * Convert a path into a url
600
- *
601
- * @param string $path
602
- * @return string url
603
- */
604
- private function getFileURLForFilePath( $path ) {
605
-
606
- $upload_dir = self::uploadDir();
607
-
608
- if ( strpos( $path, $upload_dir['basedir'] ) !== false ) {
609
- return str_replace( $upload_dir['basedir'], set_url_scheme( $upload_dir['baseurl'] ), $path );
610
-
611
- } else {
612
- return str_replace( self::get_home_path(), trailingslashit( home_url() ), $path );
613
-
614
- }
615
-
616
- }
617
-
618
- }
619
-
620
- /**
621
- * Resizes a given image (local).
622
- *
623
- * @param mixed absolute path to the image
624
- * @param int $width .
625
- * @param int $height .
626
- * @param bool $crop . (default: false)
627
- * @return (string) url to the image
628
- */
629
- function wpthumb( $url, $args = array() ) {
630
-
631
- $thumb = new WP_Thumb( $url, $args );
632
-
633
- $return = $thumb->returnImage();
634
-
635
- return $return;
636
- }
637
-
638
- /**
639
- * Hook WP Thumb into the WordPress image functions
640
- *
641
- * Usage `the_post_thumbnail( 'width=100&height=200&crop=1' );`
642
- *
643
- * @param null $null
644
- * @param int $id
645
- * @param array $args
646
- * @return null
647
- */
648
- function wpthumb_post_image( $null, $id, $args ) {
649
-
650
- // check if $args is a WP Thumb argument list, or native WordPress one
651
- // wp thumb looks like this: 'width=300&height=120&crop=1'
652
- // native looks like 'thumbnail'
653
- if ( is_string( $args ) && ! strpos( (string) $args, '=' ) ) {
654
-
655
- $original_args = $args;
656
-
657
- if ( $original_args === ( $args = apply_filters( 'wpthumb_create_args_from_size', $args ) ) ) {
658
- return $null;
659
- }
660
- }
661
-
662
- $args = wp_parse_args( $args );
663
-
664
- if ( ! empty( $args[0] ) )
665
- $args['width'] = $args[0];
666
-
667
- if ( ! empty( $args[1] ) )
668
- $args['height'] = $args[1];
669
-
670
- if ( ! empty( $args['crop'] ) && $args['crop'] && empty( $args['crop_from_position'] ) )
671
- $args['crop_from_position'] = get_post_meta( $id, 'wpthumb_crop_pos', true );
672
-
673
- if ( empty( $path ) )
674
- $path = get_attached_file( $id );
675
-
676
- $path = apply_filters( 'wpthumb_post_image_path', $path, $id, $args );
677
- $args = apply_filters( 'wpthumb_post_image_args', $args, $id );
678
-
679
- $image = new WP_Thumb( $path, $args );
680
-
681
- $args = $image->getArgs();
682
-
683
- extract( $args );
684
-
685
- if ( ! $image->errored() ) {
686
-
687
- $image_src = $image->returnImage();
688
-
689
- $crop = (bool) ( empty( $crop ) ) ? false : $crop;
690
-
691
- if ( ! $image->errored() && $image_meta = @getimagesize( $image->getCacheFilePath() ) ) :
692
-
693
- $html_width = $image_meta[0];
694
- $html_height = $image_meta[1];
695
-
696
- else :
697
- $html_width = $html_height = false;
698
-
699
- endif;
700
-
701
- } else {
702
-
703
- $html_width = $width;
704
- $html_height = $height;
705
- $image_src = $image->getFileURL();
706
- }
707
-
708
- return array( $image_src, $html_width, $html_height, true );
709
-
710
- }
711
-
712
- add_filter( 'image_downsize', 'wpthumb_post_image', 99, 3 );
713
-
714
- /**
715
- * Hook into wp_delete_file and delete the associated cache files
716
- *
717
- * @param string $file
718
- *
719
- * @return string
720
- */
721
- function wpthumb_delete_cache_for_file( $file ) {
722
-
723
- $upload_dir = wp_upload_dir();
724
-
725
- $wpthumb = new WP_Thumb( trailingslashit( $upload_dir['basedir'] ) . $file );
726
-
727
- wpthumb_rmdir_recursive( $wpthumb->getCacheFileDirectory() );
728
-
729
- return $file;
730
-
731
- }
732
-
733
- add_filter( 'wp_delete_file', 'wpthumb_delete_cache_for_file' );
734
-
735
- /**
736
- * Removes a dir tree. I.e. recursive rmdir
737
- *
738
- * @param string $dir
739
- * @return bool - success / failure
740
- */
741
- function wpthumb_rmdir_recursive( $dir ) {
742
-
743
- if ( ! is_dir( $dir ) )
744
- return false;
745
-
746
- $dir = trailingslashit( $dir );
747
-
748
- $handle = opendir( $dir );
749
-
750
- while ( false !== ( $file = readdir( $handle ) ) ) {
751
-
752
- if ( $file == '.' || $file == '..' )
753
- continue;
754
-
755
- $path = $dir . $file;
756
-
757
- if ( is_dir( $path ) )
758
- wpthumb_rmdir_recursive( $path );
759
-
760
- else
761
- unlink( $path );
762
-
763
- }
764
-
765
- closedir( $handle );
766
-
767
- rmdir( $dir );
768
-
769
- }
770
-
771
- /**
772
- * wpthumb_errors function.
773
- *
774
- * @access public
775
- * @return null
776
- */
777
- function wpthumb_errors() {
778
-
779
- $dir_upload = wp_upload_dir();
780
- $dir_upload = $dir_upload['path'];
781
-
782
- if ( file_exists( $dir_upload ) && ! is_writable( $dir_upload ) )
783
- echo '<div id="wpthumb-warning" class="updated fade"><p><strong>' . __( 'WPThumb has detected a problem.', 'wpthumb' ) . '</strong> ' . sprintf( __( 'The directory <code>%s</code> is not writable.', 'wpthumb' ), $dir_upload ) . '</p></div>';
784
-
785
- }
786
-
787
- add_action( 'admin_notices', 'wpthumb_errors' );
788
-
789
- function wpthumb_add_image_editors( $editors ) {
790
-
791
- require_once( WP_THUMB_PATH . '/wpthumb.image-editor.php' );
792
-
793
- $wpthumb_editors = array(
794
- 'WP_Thumb_Image_Editor_Imagick',
795
- 'WP_Thumb_Image_Editor_GD'
796
- );
797
-
798
- return array_unique( array_merge( $wpthumb_editors, $editors ) );
799
- }
800
-
801
- add_filter( 'wp_image_editors', 'wpthumb_add_image_editors', 99 );
802
-
803
- function wpthumb_create_args_from_size( $args = '' ) {
804
-
805
- $new_args = array();
806
-
807
- if ( 'thumbnail' === $args ) {
808
- $new_args = array(
809
- 'width' => get_option( 'thumbnail_size_w' ),
810
- 'height' => get_option( 'thumbnail_size_h' ),
811
- 'crop' => get_option( 'thumbnail_crop' ),
812
- );
813
- } elseif ( 'medium' === $args ) {
814
- $new_args = array(
815
- 'width' => get_option( 'medium_size_w' ),
816
- 'height' => get_option( 'medium_size_h' ),
817
- );
818
- } elseif ( 'large' === $args ) {
819
- $new_args = array(
820
- 'width' => get_option( 'large_size_w' ),
821
- 'height' => get_option( 'large_size_h' ),
822
- );
823
- }
824
-
825
- if ( ! empty( $new_args ) && ! empty( $new_args['width'] ) && ! empty( $new_args['height'] ) ) {
826
- return $new_args;
827
- }
828
-
829
- return $args;
830
- }
831
-
832
- add_filter( 'wpthumb_create_args_from_size', 'wpthumb_create_args_from_size' );
833
-
834
- function wpthumb_default_crop_position() {
835
- return apply_filters( 'wpthumb_default_crop_position', 'center,center' );
836
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/WPThumb/wpthumb.shortcodes.php DELETED
@@ -1,49 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * The [wpthumb] shortcode is used for resizing image URLs / attachments from within the content
5
- *
6
- * The wpthumb shortcode supports all the WP Thumb arguments, for example:
7
- *
8
- * [wpthumb 4567 width=400 height=200]
9
- */
10
-
11
- add_shortcode( 'wpthumb', 'wpthumb_img_shortcode' );
12
-
13
- function wpthumb_img_shortcode( $args ) {
14
-
15
- $args_attrs = array( 'class', 'alt' );
16
- $attrs = array();
17
-
18
- foreach ( $args_attrs as $att ) {
19
- if ( isset( $args[$att] ) ) {
20
- $attrs[$att] = $args[$att];
21
- unset( $args[$att] );
22
- }
23
- }
24
-
25
- if ( is_numeric( $args[0] ) ) {
26
-
27
- $attachment_id = $args[0];
28
- unset( $args[0] );
29
-
30
- return wp_get_attachment_image( $attachment_id, $args, false, $attrs );
31
-
32
- } else if ( ! empty( $args ) ) {
33
-
34
- $url = esc_url( $args[0] );
35
- unset( $args[0] );
36
-
37
- $image = wpthumb( $url, $args );
38
-
39
- list( $width, $height ) = getimagesize( $image );
40
-
41
- $attr = '';
42
-
43
- foreach ( $attrs as $a => $value ) {
44
- $attr .= ' ' . $a . '="' . esc_attr( $value ) . '"';
45
- }
46
-
47
- return '<img src="' . $image . '" width="' . $width . '" height="' . $height . '"' . $attr . ' />';
48
- }
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/WPThumb/wpthumb.watermark.php DELETED
@@ -1,392 +0,0 @@
1
- <?php
2
-
3
- class WP_Thumb_Watermark {
4
-
5
- private $args = array();
6
- private $editor;
7
-
8
- public function __construct( $editor, $args ) {
9
-
10
- $this->editor = $editor;
11
-
12
- $defaults = array(
13
- 'padding' => 0,
14
- 'position' => 'top,left',
15
- 'mask' => ''
16
- );
17
-
18
- $this->args = wp_parse_args( $args['watermark_options'], $defaults );
19
- $this->fill_watermark();
20
- }
21
-
22
- public function fill_watermark() {
23
-
24
- $image = $this->editor->get_image();
25
- $size = $this->editor->get_size();
26
-
27
- list( $mask_width, $mask_height, $mask_type, $mask_attr) = getimagesize( $this->args['mask'] );
28
-
29
- switch ($mask_type) {
30
- case 1:
31
- $mask = imagecreatefromgif( $this->args['mask'] );
32
- break;
33
- case 2:
34
- $mask = imagecreatefromjpeg( $this->args['mask'] );
35
- break;
36
- case 3:
37
- $mask = imagecreatefrompng( $this->args['mask'] );
38
- break;
39
- }
40
-
41
- imagealphablending( $image, true );
42
-
43
- if ( strpos( $this->args['position'], 'left' ) !== false )
44
- $left = $this->args['padding'];
45
- else
46
- $left = $size['width'] - $mask_width - $this->args['padding'];
47
-
48
-
49
- if ( strpos( $this->args['position'], 'top' ) !== false )
50
- $top = $this->args['padding'];
51
- else
52
- $top = $size['height'] - $mask_height - $this->args['padding'];
53
-
54
- imagecopy(
55
- $image,
56
- $mask,
57
- $left,
58
- $top,
59
- 0,
60
- 0,
61
- $mask_width,
62
- $mask_height
63
- );
64
-
65
- $this->editor->update_image( $image );
66
-
67
- imagedestroy( $mask );
68
- }
69
-
70
- }
71
-
72
- function wpthumb_watermark_add_args_to_post_image( $args, $id ) {
73
-
74
- if ( wpthumb_wm_image_has_watermark( $id ) )
75
- $args['watermark_options'] = wpthumb_wm_get_options( $id );
76
-
77
- return $args;
78
- }
79
- add_filter( 'wpthumb_post_image_args', 'wpthumb_watermark_add_args_to_post_image', 10, 2 );
80
-
81
- /**
82
- * Hook into WP Thumb before it resizes an image to possible apply a watermatk
83
- *
84
- * @param WP_IMageEditor $editor
85
- * @param array $args
86
- */
87
- function wpthumb_watermark_pre( $editor, $args ) {
88
-
89
- // currently only supports GD
90
- if ( ! is_a( $editor, 'WP_Thumb_Image_Editor_GD') || empty( $args['watermark_options'] ) )
91
- return $editor;
92
-
93
- // we only want pre
94
- if ( empty( $args['watermark_options']['pre_resize'] ) )
95
- return;
96
-
97
- new WP_Thumb_Watermark( $editor, $args );
98
-
99
- return $editor;
100
- }
101
- add_filter( 'wpthumb_image_pre', 'wpthumb_watermark_pre', 10, 2 );
102
-
103
- function wpthumb_watermark_post( $editor, $args ) {
104
-
105
- // currently only supports GD
106
- if ( ! is_a( $editor, 'WP_Thumb_Image_Editor_GD') || empty( $args['watermark_options'] ) )
107
- return $editor;
108
-
109
- // we only want pre
110
- if ( isset( $args['watermark_options']['pre_resize'] ) && $args['watermark_options']['pre_resize'] === true )
111
- return;
112
-
113
- new WP_Thumb_Watermark( $editor, $args );
114
-
115
- return $editor;
116
- }
117
- add_filter( 'wpthumb_image_post', 'wpthumb_watermark_post', 10, 2 );
118
-
119
- /**
120
- * wpthumb_media_form_crop_position function.
121
- *
122
- * Adds a back end for selecting the crop position of images.
123
- *
124
- * @access public
125
- * @param array $fields
126
- * @param array $post
127
- * @return $post
128
- */
129
- function wpthumb_media_form_watermark_position( $fields, $post ) {
130
-
131
- if ( ! wp_attachment_is_image( $post->ID ) )
132
- return $fields;
133
-
134
- $current_position = get_post_meta( $post->ID, 'wpthumb_wm_position', true );
135
-
136
- if ( ! $current_position )
137
- $current_position = 'top-left';
138
-
139
- ob_start();
140
-
141
- ?>
142
-
143
- <style>
144
- #wpthumb_crop_pos { }
145
- .go-left { margin-left: -93px; width: 80px; display: inline-block; margin-right: 10px; text-align: right; color: #999; }
146
- #wpthumb_watermark_pos { margin: 10px 0 }
147
- #wpthumb_watermark_pos input { margin: 3px; width: auto; }
148
- </style>
149
-
150
- <div id="wm-options-<?php echo $post->ID ?>">
151
- <p>
152
- <label>
153
- <input class="wm-toggle-watermark" type="checkbox" style="width: 20px" <?php checked( wpthumb_wm_image_has_watermark( $post->ID ) ) ?> name="attachments[<?php echo $post->ID ?>][wpthumb_wm_use_watermark]" /> Apply Watermark
154
- </label>
155
- </p>
156
- <div class="wpthumb_watermark_options <?php echo wpthumb_wm_image_has_watermark( $post->ID ) ? '' : 'hidden' ?>">
157
-
158
- <div>
159
- <label class="go-left">Mask</label>
160
- <select name="attachments[<?php echo $post->ID ?>][wm_watermark_mask]">
161
- <?php foreach( wpthumb_wm_get_watermark_masks() as $mask_id => $watermark_mask ) : ?>
162
- <option value="<?php echo $mask_id ?>" <?php selected( wpthumb_wm_mask( $post->ID ) == $mask_id ) ?>><?php echo $watermark_mask['label'] ?></option>
163
- <?php endforeach; ?>
164
- </select>
165
- </div>
166
-
167
- <div id="wpthumb_watermark_pos">
168
- <label class="go-left">Position</label>
169
- <input type="radio" name="attachments[<?php echo $post->ID ?>][wpthumb_wm_watermark_position]" value="top-left" title="Left, Top" <?php checked( 'top-left', $current_position ) ?>/>
170
- <input type="radio" name="attachments[<?php echo $post->ID ?>][wpthumb_wm_watermark_position]" value="top-right" title="Center, Top" <?php checked( 'top-right', $current_position ) ?> /><br />
171
- <input type="radio" name="attachments[<?php echo $post->ID ?>][wpthumb_wm_watermark_position]" value="bottom-left" title="Right, Top" <?php checked( 'bottom-left', $current_position ) ?> />
172
- <input type="radio" name="attachments[<?php echo $post->ID ?>][wpthumb_wm_watermark_position]" value="bottom-right" title="Left, Center" <?php checked( 'bottom-right', $current_position ) ?> />
173
- </div>
174
-
175
- <div id="">
176
- <label class="go-left">Padding</label>
177
- <input type="number" value="<?php echo wpthumb_wm_padding( $post->ID ) ?>" name="attachments[<?php echo $post->ID ?>][wpthumb_wm_watermark_padding]" style="width: 40px" />
178
- </div>
179
- </div>
180
- </div>
181
- <script>
182
-
183
- jQuery( '#wm-options-<?php echo $post->ID ?>' ).live( 'change', '.wm-toggle-watermark', function(e) {
184
-
185
- jQuery( e.target ).closest( 'p' ).next().toggle();
186
- });
187
- </script>
188
- <?php
189
- $html = ob_get_clean();
190
-
191
- $fields['watermark-position'] = array(
192
- 'label' => __( 'Watermark', 'wpthumb' ),
193
- 'input' => 'html',
194
- 'html' => $html
195
- );
196
-
197
- return $fields;
198
-
199
- }
200
-
201
- /**
202
- * Only add the watermkaring admin optins if the current theme suports it, as we don;t want to clutter
203
- * for poeple who don't care
204
- *
205
- */
206
- function wpthumb_add_watermarking_admin_hooks() {
207
-
208
- if ( current_theme_supports( 'wpthumb-watermarking' ) ) {
209
- add_filter( 'attachment_fields_to_edit', 'wpthumb_media_form_watermark_position', 10, 2 );
210
- add_filter( 'attachment_fields_to_save', 'wpthumb_media_form_watermark_save', 10, 2);
211
- }
212
- }
213
- add_action( 'init', 'wpthumb_add_watermarking_admin_hooks' );
214
-
215
- /**
216
- * wpthumb_media_form_watermark_save function.
217
- *
218
- * Saves watermark in post meta.
219
- *
220
- * @access public
221
- * @param array $post
222
- * @param array $attachment
223
- * @return $post
224
- */
225
- function wpthumb_media_form_watermark_save( $post, $attachment ){
226
-
227
- if ( ! empty( $attachment['wpthumb_wm_use_watermark'] ) ) {
228
- update_post_meta( $post['ID'], 'use_watermark', true );
229
- update_post_meta( $post['ID'], 'wpthumb_wm_position', $attachment['wpthumb_wm_watermark_position'] );
230
- update_post_meta( $post['ID'], 'wpthumb_wm_padding', (int) $attachment['wpthumb_wm_watermark_padding'] );
231
- update_post_meta( $post['ID'], 'wpthumb_wm_pre_resize', '0' );
232
- update_post_meta( $post['ID'], 'wpthumb_wm_mask', $attachment['wm_watermark_mask'] );
233
-
234
- } else {
235
- delete_post_meta( $post['ID'], 'use_watermark' );
236
- delete_post_meta( $post['ID'], 'wpthumb_wm_position' );
237
- delete_post_meta( $post['ID'], 'wpthumb_wm_padding' );
238
- delete_post_meta( $post['ID'], 'wpthumb_wm_pre_resize' );
239
- delete_post_meta( $post['ID'], 'wpthumb_wm_mask' );
240
- }
241
-
242
- return $post;
243
- }
244
-
245
- /**
246
- * wpthumb_wm_get_options function.
247
- *
248
- * @access public
249
- * @param mixed $id
250
- * @return array
251
- */
252
- function wpthumb_wm_get_options( $id ) {
253
-
254
- if ( ! wpthumb_wm_image_has_watermark( $id ) )
255
- return array();
256
-
257
- $options['mask'] = get_template_directory() . '/images/watermark.png';
258
-
259
- $mask = wpthumb_wm_mask( $id );
260
-
261
- if( ! empty( $mask ) ) {
262
- $options['mask'] = wpthumb_wm_get_watermark_mask_file( $mask );
263
- } else {
264
- $mask = wpthumb_wm_get_default_watermark_mask();
265
- $options['mask'] = $mask['file'];
266
- }
267
-
268
- $options['padding'] = wpthumb_wm_padding($id);
269
- $position = wpthumb_wm_position( $id );
270
-
271
- $options['position'] = $position;
272
-
273
- return $options;
274
- }
275
-
276
- /**
277
- * wpthumb_wm_image_has_watermark function.
278
- *
279
- * @access public
280
- * @param mixed $image_id
281
- * @return null
282
- */
283
- function wpthumb_wm_image_has_watermark( $image_id ) {
284
- return (bool) get_post_meta( $image_id, 'use_watermark', true );
285
- }
286
-
287
- /**
288
- * wpthumb_wm_position function.
289
- *
290
- * @access public
291
- * @param mixed $image_id
292
- * @return null
293
- */
294
- function wpthumb_wm_position( $image_id ) {
295
-
296
- if ( $pos = get_post_meta( $image_id, 'wpthumb_wm_position', true ) )
297
- return $pos;
298
-
299
- //legacy
300
- if ( $pos = get_post_meta( $image_id, 'wm_position', true ) )
301
- return $pos;
302
- }
303
-
304
- /**
305
- * wpthumb_wm_padding function.
306
- *
307
- * @access public
308
- * @param mixed $image_id
309
- * @return null
310
- */
311
- function wpthumb_wm_padding( $image_id ) {
312
-
313
- if ( $padding = (int) get_post_meta( $image_id, 'wpthumb_wm_padding', true ) )
314
- return $padding;
315
-
316
- //legacy
317
- if ( $padding = (int) get_post_meta( $image_id, 'wm_padding', true ) )
318
- return $padding;
319
- }
320
-
321
- function wpthumb_wm_pre_resize( $image_id ) {
322
-
323
- if ( $pre = (bool) get_post_meta( $image_id, 'wpthumb_wm_pre_resize', true ) )
324
- return $pre;
325
-
326
- //legacy
327
- if ( $pre = (bool) get_post_meta( $image_id, 'wm_pre_resize', true ) )
328
- return $pre;
329
-
330
- }
331
- function wpthumb_wm_mask( $image_id ) {
332
-
333
- if ( $pre = (string) get_post_meta( $image_id, 'wpthumb_wm_mask', true ) )
334
- return $pre;
335
-
336
- //legacy
337
- if ( $pre = (string) get_post_meta( $image_id, 'wm_mask', true ) )
338
- return $pre;
339
-
340
- }
341
-
342
- /**
343
- * Returns all the watermarks that are registered
344
- *
345
- * @return array
346
- */
347
- function wpthumb_wm_get_watermark_masks() {
348
- global $_wm_registered_watermarks;
349
- $_wm_registered_watermarks = (array) $_wm_registered_watermarks;
350
-
351
- $masks = array( 'default' => array( 'file' => get_stylesheet_directory() . '/images/watermark.png', 'label' => 'Default' ) );
352
-
353
- $masks = array_merge( $masks, $_wm_registered_watermarks );
354
-
355
- return $masks;
356
- }
357
-
358
- /**
359
- * Returns the watermarking image file for a given watermark name
360
- *
361
- * @param string $mask
362
- * @return string
363
- */
364
- function wpthumb_wm_get_watermark_mask_file( $mask ) {
365
- $masks = wpthumb_wm_get_watermark_masks();
366
- return $masks[$mask]['file'];
367
- }
368
-
369
- /**
370
- * Registers extra watermark images for the user to select in the admin
371
- *
372
- * @param string $name - sanitized identifier
373
- * @param string $file - full path to the watermarking image
374
- * @param string $label - test to be used for the watermarks name
375
- */
376
- function wpthumb_wm_register_watermark( $name, $file, $label ) {
377
-
378
- global $_wm_registered_watermarks;
379
- $_wm_registered_watermarks = (array) $_wm_registered_watermarks;
380
-
381
- $_wm_registered_watermarks[$name] = array( 'file' => $file, 'label' => $label );
382
- }
383
-
384
- /**
385
- * Returns the default watermask array ( file => string, label => string )
386
- *
387
- * @return array
388
- */
389
- function wpthumb_wm_get_default_watermark_mask() {
390
- $masks = wpthumb_wm_get_watermark_masks();
391
- return $masks['default'];
392
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/class-admin.php CHANGED
@@ -17,7 +17,6 @@ if ( ! class_exists( 'FooGallery_Admin' ) ) {
17
  //init some other actions
18
  add_action( 'init', array( $this, 'init' ) );
19
 
20
- new FooGallery_Admin_Settings_Image_Optimization();
21
  new FooGallery_Admin_Settings();
22
  new FooGallery_Admin_Menu();
23
  new FooGallery_Admin_Gallery_Editor();
17
  //init some other actions
18
  add_action( 'init', array( $this, 'init' ) );
19
 
 
20
  new FooGallery_Admin_Settings();
21
  new FooGallery_Admin_Menu();
22
  new FooGallery_Admin_Gallery_Editor();
includes/admin/class-gallery-metabox-items.php CHANGED
@@ -120,7 +120,7 @@ if ( ! class_exists( 'FooGallery_Admin_Gallery_MetaBox_Items' ) ) {
120
  $args = apply_filters( 'foogallery_preview_arguments-' . $template, $args, $_POST );
121
 
122
  if ( foogallery_is_debug() ) {
123
- echo '<pre>' . __('Preview Debug Arguments:', 'foogallery') . '<br>' . print_r( $args, true ) . '</pre>';
124
  }
125
 
126
  foogallery_render_gallery( $foogallery_id, $args );
120
  $args = apply_filters( 'foogallery_preview_arguments-' . $template, $args, $_POST );
121
 
122
  if ( foogallery_is_debug() ) {
123
+ echo '<pre style="display: none">' . __('Preview Debug Arguments:', 'foogallery') . '<br>' . print_r( $args, true ) . '</pre>';
124
  }
125
 
126
  foogallery_render_gallery( $foogallery_id, $args );
includes/admin/class-gallery-metaboxes.php CHANGED
@@ -311,7 +311,11 @@ if ( ! class_exists( 'FooGallery_Admin_Gallery_MetaBoxes' ) ) {
311
  public function render_thumb_settings_metabox( $post ) {
312
  $gallery = $this->get_gallery( $post );
313
  $force_use_original_thumbs = get_post_meta( $post->ID, FOOGALLERY_META_FORCE_ORIGINAL_THUMBS, true );
314
- $checked = 'true' === $force_use_original_thumbs; ?>
 
 
 
 
315
  <p>
316
  <?php _e( 'Clear all the previously cached thumbnails that have been generated for this gallery.', 'foogallery' ); ?>
317
  </p>
@@ -320,6 +324,7 @@ if ( ! class_exists( 'FooGallery_Admin_Gallery_MetaBoxes' ) ) {
320
  <span id="foogallery_clear_thumb_cache_spinner" class="spinner"></span>
321
  <?php wp_nonce_field( 'foogallery_clear_gallery_thumb_cache', 'foogallery_clear_gallery_thumb_cache_nonce', false ); ?>
322
  </div>
 
323
  <p>
324
  <input type="checkbox" value="true" <?php checked( $checked ); ?> id="FooGallerySettings_ForceOriginalThumbs" name="<?php echo FOOGALLERY_META_FORCE_ORIGINAL_THUMBS; ?>" />
325
  <label for="FooGallerySettings_ForceOriginalThumbs"><?php _e('Force Original Thumbs', 'foogallery'); ?></label>
@@ -394,24 +399,27 @@ if ( ! class_exists( 'FooGallery_Admin_Gallery_MetaBoxes' ) ) {
394
  public function ajax_clear_gallery_thumb_cache() {
395
  if ( check_admin_referer( 'foogallery_clear_gallery_thumb_cache', 'foogallery_clear_gallery_thumb_cache_nonce' ) ) {
396
 
397
- $foogallery_id = $_POST['foogallery_id'];
398
 
399
- $foogallery = FooGallery::get_by_id( $foogallery_id );
400
 
401
- ob_start();
402
 
403
- //loop through all images, get the full sized file
404
- foreach ( $foogallery->attachments() as $attachment ) {
405
- $meta_data = wp_get_attachment_metadata( $attachment->ID );
406
 
407
- $file = $meta_data['file'];
408
 
409
- wpthumb_delete_cache_for_file( $file );
410
- }
 
 
411
 
412
- ob_end_clean();
413
 
414
- echo __( 'The thumbnail cache has been cleared!', 'foogallery' );
 
 
 
415
  }
416
 
417
  die();
311
  public function render_thumb_settings_metabox( $post ) {
312
  $gallery = $this->get_gallery( $post );
313
  $force_use_original_thumbs = get_post_meta( $post->ID, FOOGALLERY_META_FORCE_ORIGINAL_THUMBS, true );
314
+ $checked = 'true' === $force_use_original_thumbs;
315
+
316
+ $engine = foogallery_thumb_active_engine();
317
+
318
+ if ( $engine->has_local_cache() ) { ?>
319
  <p>
320
  <?php _e( 'Clear all the previously cached thumbnails that have been generated for this gallery.', 'foogallery' ); ?>
321
  </p>
324
  <span id="foogallery_clear_thumb_cache_spinner" class="spinner"></span>
325
  <?php wp_nonce_field( 'foogallery_clear_gallery_thumb_cache', 'foogallery_clear_gallery_thumb_cache_nonce', false ); ?>
326
  </div>
327
+ <?php } ?>
328
  <p>
329
  <input type="checkbox" value="true" <?php checked( $checked ); ?> id="FooGallerySettings_ForceOriginalThumbs" name="<?php echo FOOGALLERY_META_FORCE_ORIGINAL_THUMBS; ?>" />
330
  <label for="FooGallerySettings_ForceOriginalThumbs"><?php _e('Force Original Thumbs', 'foogallery'); ?></label>
399
  public function ajax_clear_gallery_thumb_cache() {
400
  if ( check_admin_referer( 'foogallery_clear_gallery_thumb_cache', 'foogallery_clear_gallery_thumb_cache_nonce' ) ) {
401
 
402
+ $engine = foogallery_thumb_active_engine();
403
 
404
+ if ( $engine->has_local_cache() ) {
405
 
406
+ $foogallery_id = $_POST['foogallery_id'];
407
 
408
+ $foogallery = FooGallery::get_by_id( $foogallery_id );
 
 
409
 
410
+ ob_start();
411
 
412
+ //loop through all images, get the full sized file
413
+ foreach ( $foogallery->attachments() as $attachment ) {
414
+ $engine->clear_local_cache_for_file( $attachment->url );
415
+ }
416
 
417
+ ob_end_clean();
418
 
419
+ echo __( 'The thumbnail cache has been cleared!', 'foogallery' );
420
+ } else {
421
+ echo __( 'There was no thumbnail cache to clear.', 'foogallery' );
422
+ }
423
  }
424
 
425
  die();
includes/admin/class-settings-image-optimization.php DELETED
@@ -1,32 +0,0 @@
1
- <?php
2
-
3
- if ( ! class_exists( 'FooGallery_Admin_Settings_Image_Optimization' ) ) {
4
-
5
- define( 'FOOGALLERY_SETTINGS_IMAGE_OPTIMIZATION_ENDPOINT', 'https://fooplugins.com/foogallery-image-optimization.html' );
6
-
7
- /**
8
- * Class FooGallery_Admin_Settings_Image_Optimization
9
- */
10
- class FooGallery_Admin_Settings_Image_Optimization {
11
-
12
- function __construct() {
13
- add_filter( 'foogallery_admin_settings_override', array($this, 'add_image_optimization_info' ) );
14
- }
15
-
16
- function add_image_optimization_info( $settings ) {
17
-
18
- $image_optimization_html = sprintf( __('Try the %s, an easy-to-use, lightweight WordPress plugin that optimizes images & PDFs.', 'foogallery'),
19
- '<a href="https://shortpixel.com/homepage/affiliate/foowww" target="_blank">' . __('ShortPixel Image Optimizer' , 'foogallery') . '</a>' );
20
-
21
- $settings['settings'][] = array(
22
- 'id' => 'image_optimization',
23
- 'title' => __( 'Image Optimization', 'foogallery' ),
24
- 'type' => 'html',
25
- 'desc' => $image_optimization_html,
26
- 'tab' => 'thumb'
27
- );
28
-
29
- return $settings;
30
- }
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/class-settings.php CHANGED
@@ -155,18 +155,35 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
155
  //region Images Tab
156
  $tabs['thumb'] = __( 'Images', 'foogallery' );
157
 
158
- $image_editor = str_replace( 'WP_Thumb_Image_Editor_', '', _wp_image_editor_choose( array( 'methods' => array( 'get_image' ) ) ) );
159
- $gd_supported = extension_loaded( 'gd' ) ? __('yes', 'foogallery') : __('no', 'foogallery');
160
- $imagick_supported = extension_loaded( 'imagick' ) ? __('yes', 'foogallery') : __('no', 'foogallery');
 
161
 
162
  $settings[] = array(
163
- 'id' => 'thumb_image_library',
164
- 'title' => __( 'Thumbnail Image Library', 'foogallery' ),
165
- 'desc' => sprintf( __('Currently active : %s.<br />Imagick supported : %s.<br />GD supported : %s.', 'foogallery'), '<strong>' . $image_editor . '</strong>', $imagick_supported, $gd_supported ),
166
- 'type' => 'html',
 
 
167
  'tab' => 'thumb'
168
  );
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  $settings[] = array(
171
  'id' => 'thumb_jpeg_quality',
172
  'title' => __( 'Thumbnail JPEG Quality', 'foogallery' ),
@@ -176,6 +193,17 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
176
  'tab' => 'thumb'
177
  );
178
 
 
 
 
 
 
 
 
 
 
 
 
179
  $settings[] = array(
180
  'id' => 'default_retina_support',
181
  'title' => __( 'Default Retina Support', 'foogallery' ),
@@ -186,21 +214,23 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
186
  );
187
 
188
  $settings[] = array(
189
- 'id' => 'use_original_thumbs',
190
- 'title' => __( 'Use Original Thumbnails', 'foogallery' ),
191
- 'desc' => __( 'Allow for the original thumbnails to be used when possible. This can be useful if your thumbs are animated gifs.<br/>PLEASE NOTE : this will only work if your gallery thumbnail sizes are identical to your thumbnail sizes under Settings -> Media.', 'foogallery' ),
192
- 'type' => 'checkbox',
193
- 'tab' => 'thumb'
194
- );
195
-
196
- $settings[] = array(
197
- 'id' => 'thumb_resize_animations',
198
- 'title' => __( 'Resize Animated GIFs', 'foogallery' ),
199
- 'desc' => __( 'Should animated gifs be resized or not. If enabled, only the first frame is used in the resize.', 'foogallery' ),
200
  'type' => 'checkbox',
201
  'tab' => 'thumb'
202
  );
203
 
 
 
 
 
 
 
 
 
 
 
204
  $settings[] = array(
205
  'id' => 'animated_gif_use_original_image',
206
  'title' => __( 'Show Animated Thumbnails', 'foogallery' ),
@@ -209,39 +239,46 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
209
  'tab' => 'thumb'
210
  );
211
 
212
- $settings[] = array(
213
- 'id' => 'thumb_resize_upscale_small',
214
- 'title' => __( 'Upscale Small Images', 'foogallery' ),
215
- 'desc' => __( 'If the original image is smaller than the thumbnail size, then upscale the image thumbnail to match the size.', 'foogallery') . '<br/>' .
216
- __('PLEASE NOTE : this is only supported if your server supports the GD image library and it is currently active.', 'foogallery' ),
217
- 'type' => 'checkbox',
218
- 'tab' => 'thumb'
219
- );
220
 
221
- $settings[] = array(
222
- 'id' => 'thumb_resize_upscale_small_color',
223
- 'title' => __( 'Upscale Background Color', 'foogallery' ),
224
- 'desc' => __( 'The background color to use for upscaled images.', 'foogallery' ),
225
- 'type' => 'text',
226
- 'default' => 'rgb(0,0,0)',
227
- 'tab' => 'thumb'
228
- );
 
229
 
230
- $settings[] = array(
231
- 'id' => 'thumb_generation_test',
232
- 'title' => __( 'Thumbnail Generation Test', 'foogallery' ),
233
- 'desc' => sprintf( __( 'Test to see if %s can generate the thumbnails it needs.', 'foogallery' ), foogallery_plugin_name() ),
234
- 'type' => 'thumb_generation_test',
235
- 'tab' => 'thumb'
236
- );
237
 
238
- $settings[] = array(
239
- 'id' => 'force_gd_library',
240
- 'title' => __( 'Force GD Library', 'foogallery' ),
241
- 'desc' => __( 'By default, WordPress will use Imagick as the default Image Editor. This will force GD to be used as the default.', 'foogallery' ),
242
- 'type' => 'checkbox',
243
- 'tab' => 'thumb'
244
- );
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  //endregion Thumbnail Tab
247
 
@@ -489,7 +526,7 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
489
  }
490
 
491
  /**
492
- * AJAX endpoint for testing thumbnail generation using WPThumb
493
  */
494
  function ajax_thumb_generation_test() {
495
  if ( check_admin_referer( 'foogallery_thumb_generation_test' ) ) {
@@ -601,15 +638,16 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
601
  }
602
 
603
  function generate_custom_asset( $filename, $contents ) {
604
- global $wp_filesystem;
605
-
606
  $upload_dir = wp_upload_dir();
607
  if ( !empty( $upload_dir['basedir'] ) ) {
608
  $dir = trailingslashit( $upload_dir['basedir'] ) . 'foogallery/';
609
- WP_Filesystem(); // Initial WP file system
610
- $wp_filesystem->mkdir( $dir ); // Make a new folder for storing our file
611
- if ( $wp_filesystem->put_contents( $dir . $filename, $contents, 0644 ) ) {
612
- return set_url_scheme( trailingslashit( $upload_dir['baseurl'] ) . 'foogallery/' . $filename );
 
 
 
613
  }
614
  }
615
 
155
  //region Images Tab
156
  $tabs['thumb'] = __( 'Images', 'foogallery' );
157
 
158
+ $engines = array();
159
+ foreach ( foogallery_thumb_available_engines() as $engine_key => $engine ) {
160
+ $engines[$engine_key] = '<strong>' . $engine['label'] . '</strong> - ' . $engine['description'];
161
+ }
162
 
163
  $settings[] = array(
164
+ 'id' => 'thumb_engine',
165
+ 'title' => __( 'Thumbnail Engine', 'foogallery' ),
166
+ 'desc' => __( 'The thumbnail generation engine used when creating different sized thumbnails for your galleries.', 'foogallery' ),
167
+ 'type' => 'radio',
168
+ 'default' => 'default',
169
+ 'choices' => $engines,
170
  'tab' => 'thumb'
171
  );
172
 
173
+ if ( foogallery_thumb_active_engine()->uses_image_editors() ) {
174
+ $image_editor = str_replace( 'FooGallery_Thumb_Image_Editor_', '', _wp_image_editor_choose( array( 'methods' => array( 'get_image' ) ) ) );
175
+ $gd_supported = extension_loaded( 'gd' ) ? __( 'yes', 'foogallery' ) : __( 'no', 'foogallery' );
176
+ $imagick_supported = extension_loaded( 'imagick' ) ? __( 'yes', 'foogallery' ) : __( 'no', 'foogallery' );
177
+
178
+ $settings[] = array(
179
+ 'id' => 'thumb_image_library',
180
+ 'title' => __( 'Thumbnail Image Library', 'foogallery' ),
181
+ 'desc' => sprintf( __( 'Currently active : %s.<br />Imagick supported : %s.<br />GD supported : %s.', 'foogallery' ), '<strong>' . $image_editor . '</strong>', $imagick_supported, $gd_supported ),
182
+ 'type' => 'html',
183
+ 'tab' => 'thumb'
184
+ );
185
+ }
186
+
187
  $settings[] = array(
188
  'id' => 'thumb_jpeg_quality',
189
  'title' => __( 'Thumbnail JPEG Quality', 'foogallery' ),
193
  'tab' => 'thumb'
194
  );
195
 
196
+ $image_optimization_html = sprintf( __('We recommend %s! An easy-to-use, lightweight WordPress plugin that optimizes images & PDFs.', 'foogallery'),
197
+ '<a href="https://shortpixel.com/homepage/affiliate/foowww" target="_blank">' . __('ShortPixel Image Optimizer' , 'foogallery') . '</a>' );
198
+
199
+ $settings[] = array(
200
+ 'id' => 'image_optimization',
201
+ 'title' => __( 'Image Optimization', 'foogallery' ),
202
+ 'type' => 'html',
203
+ 'desc' => $image_optimization_html,
204
+ 'tab' => 'thumb'
205
+ );
206
+
207
  $settings[] = array(
208
  'id' => 'default_retina_support',
209
  'title' => __( 'Default Retina Support', 'foogallery' ),
214
  );
215
 
216
  $settings[] = array(
217
+ 'id' => 'use_original_thumbs',
218
+ 'title' => __( 'Use Original Thumbnails', 'foogallery' ),
219
+ 'desc' => __( 'Allow for the original thumbnails to be used when possible. This can be useful if your thumbs are animated gifs.<br/>PLEASE NOTE : this will only work if your gallery thumbnail sizes are identical to your thumbnail sizes under Settings -> Media.', 'foogallery' ),
 
 
 
 
 
 
 
 
220
  'type' => 'checkbox',
221
  'tab' => 'thumb'
222
  );
223
 
224
+ // This setting is not ever used, so there is no point in showing it
225
+ //
226
+ // $settings[] = array(
227
+ // 'id' => 'thumb_resize_animations',
228
+ // 'title' => __( 'Resize Animated GIFs', 'foogallery' ),
229
+ // 'desc' => __( 'Should animated gifs be resized or not. If enabled, only the first frame is used in the resize.', 'foogallery' ),
230
+ // 'type' => 'checkbox',
231
+ // 'tab' => 'thumb'
232
+ // );
233
+
234
  $settings[] = array(
235
  'id' => 'animated_gif_use_original_image',
236
  'title' => __( 'Show Animated Thumbnails', 'foogallery' ),
239
  'tab' => 'thumb'
240
  );
241
 
242
+ if ( foogallery_thumb_active_engine()->has_local_cache() ) {
243
+ $settings[] = array(
244
+ 'id' => 'thumb_resize_upscale_small',
245
+ 'title' => __( 'Upscale Small Images', 'foogallery' ),
246
+ 'desc' => __( 'If the original image is smaller than the thumbnail size, then upscale the image thumbnail to match the size.', 'foogallery' ) . '<br/>' . __( 'PLEASE NOTE : this is only supported if your server supports the GD image library and it is currently active.', 'foogallery' ),
247
+ 'type' => 'checkbox',
248
+ 'tab' => 'thumb'
249
+ );
250
 
251
+ $settings[] = array(
252
+ 'id' => 'thumb_resize_upscale_small_color',
253
+ 'title' => __( 'Upscale Background Color', 'foogallery' ),
254
+ 'desc' => __( 'The background color to use for upscaled images. You can also use "transparent" or "auto".', 'foogallery' ),
255
+ 'type' => 'text',
256
+ 'default' => 'rgb(0,0,0)',
257
+ 'tab' => 'thumb'
258
+ );
259
+ }
260
 
261
+ if ( foogallery_thumb_active_engine()->requires_thumbnail_generation_tests() ) {
262
+ $thumb_test_html = '<a href="' . admin_url( add_query_arg( array( 'page' => 'foogallery_thumb_test' ), foogallery_admin_menu_parent_slug() ) ) . '">' . __( 'View Thumb Test Page', 'foogallery' ) . '</a>';
 
 
 
 
 
263
 
264
+ $settings[] = array(
265
+ 'id' => 'thumb_generation_test',
266
+ 'title' => __( 'Thumbnail Generation Test', 'foogallery' ),
267
+ 'desc' => sprintf( __( 'Test to see if %s can generate the thumbnails it needs. %s', 'foogallery' ), foogallery_plugin_name(), $thumb_test_html ),
268
+ 'type' => 'thumb_generation_test',
269
+ 'tab' => 'thumb'
270
+ );
271
+ }
272
+
273
+ if ( foogallery_thumb_active_engine()->uses_image_editors() ) {
274
+ $settings[] = array(
275
+ 'id' => 'force_gd_library',
276
+ 'title' => __( 'Force GD Library', 'foogallery' ),
277
+ 'desc' => __( 'By default, WordPress will use Imagick as the default Image Editor. This will force GD to be used as the default.', 'foogallery' ),
278
+ 'type' => 'checkbox',
279
+ 'tab' => 'thumb'
280
+ );
281
+ }
282
 
283
  //endregion Thumbnail Tab
284
 
526
  }
527
 
528
  /**
529
+ * AJAX endpoint for testing thumbnail generation
530
  */
531
  function ajax_thumb_generation_test() {
532
  if ( check_admin_referer( 'foogallery_thumb_generation_test' ) ) {
638
  }
639
 
640
  function generate_custom_asset( $filename, $contents ) {
 
 
641
  $upload_dir = wp_upload_dir();
642
  if ( !empty( $upload_dir['basedir'] ) ) {
643
  $dir = trailingslashit( $upload_dir['basedir'] ) . 'foogallery/';
644
+
645
+ $fs = foogallery_wp_filesystem();
646
+ if ( false !== $fs ) {
647
+ $fs->mkdir( $dir ); // Make a new folder for storing our file
648
+ if ( $fs->put_contents( $dir . $filename, $contents, 0644 ) ) {
649
+ return set_url_scheme( trailingslashit( $upload_dir['baseurl'] ) . 'foogallery/' . $filename );
650
+ }
651
  }
652
  }
653
 
includes/class-foogallery-crop-position.php ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class to provide a way to override the default attachment crop position. Handy if you want to override the default of center,center
4
+ * Date: 19/02/2018
5
+ *
6
+ * @since 1.4.18
7
+ */
8
+ if ( ! class_exists( 'FooGallery_Crop_Position' ) ) {
9
+
10
+ class FooGallery_Crop_Position {
11
+
12
+ const CROP_POSITION_META_KEY = 'foogallery_crop_pos';
13
+ const CROP_POSITION_META_KEY_LEGACY = 'wpthumb_crop_pos';
14
+ const CROP_POSITION_DEFAULT = 'center,center';
15
+
16
+ function __construct() {
17
+ if ( is_admin() ) {
18
+ add_filter( 'foogallery_admin_settings_override', array( $this, 'add_default_crop_position_setting' ) );
19
+ add_action( 'foogallery_admin_settings_custom_type_render_setting', array( $this, 'render_crop_position_setting' ) );
20
+
21
+ add_filter( 'attachment_fields_to_edit', array( $this, 'media_form_crop_position' ), 10, 2 );
22
+ add_filter( 'attachment_fields_to_save', array( $this, 'media_form_crop_position_save' ), 10, 2 );
23
+ }
24
+ add_filter( 'foogallery_thumbnail_resize_args_final', array( $this, 'add_crop_position_arguments' ), 10, 3 );
25
+ }
26
+
27
+ /**
28
+ * Append crop position arguments if they are saved
29
+ *
30
+ * @param $args
31
+ * @param $original_image_src
32
+ * @param $thumbnail_object
33
+ *
34
+ * @return mixed
35
+ */
36
+ function add_crop_position_arguments( $args, $original_image_src, $thumbnail_object ) {
37
+ if ( !foogallery_thumb_active_engine()->has_local_cache() ) {
38
+ return $args;
39
+ }
40
+
41
+ if ( isset( $thumbnail_object ) && $thumbnail_object->ID > 0 ) {
42
+ $crop_from_position = get_post_meta( $thumbnail_object->ID, self::CROP_POSITION_META_KEY, true );
43
+
44
+ if ( !empty( $crop_from_position ) ) {
45
+ $args['crop_from_position'] = $crop_from_position;
46
+ }
47
+ }
48
+
49
+ return $args;
50
+ }
51
+
52
+ /**
53
+ * Adds the crop position setting to the settings array
54
+ *
55
+ * @param $settings
56
+ *
57
+ * @return mixed
58
+ */
59
+ function add_default_crop_position_setting( $settings ) {
60
+ if ( !foogallery_thumb_active_engine()->has_local_cache() ) {
61
+ return $settings;
62
+ }
63
+
64
+ $just_settings = $settings['settings'];
65
+ $position = 0;
66
+ //find the position of the 'thumb_jpeg_quality' setting
67
+ foreach( $just_settings as $setting ) {
68
+ $position++;
69
+ if ( 'thumb_jpeg_quality' === $setting['id'] ) {
70
+ break;
71
+ }
72
+ }
73
+
74
+ $new_settings[] = array(
75
+ 'id' => 'default_crop_position',
76
+ 'title' => __( 'Default Crop Position', 'foogallery' ),
77
+ 'desc' => __( 'The default crop position when resizing thumbnails.', 'foogallery' ),
78
+ 'type' => 'crop',
79
+ 'default' => self::CROP_POSITION_DEFAULT,
80
+ 'tab' => 'thumb'
81
+ );
82
+
83
+ array_splice( $just_settings, $position, 0, $new_settings );
84
+
85
+ $settings['settings'] = $just_settings;
86
+
87
+ return $settings;
88
+ }
89
+
90
+ /**
91
+ * Render the custom crop position to the settings page
92
+ *
93
+ * @param array $args
94
+ */
95
+ function render_crop_position_setting( $args ) {
96
+ if ( 'crop' === $args['type'] ) {
97
+ $current_position = foogallery_get_setting( 'default_crop_position', 'center,center'); ?>
98
+ <style>.foogallery_crop_pos input { margin: 5px !important; width: auto; }</style>
99
+ <div class="foogallery_crop_pos">
100
+ <input type="radio" name="foogallery[default_crop_position]" value="left,top" title="Left, Top" <?php checked( 'left,top', $current_position ) ?>/>
101
+ <input type="radio" name="foogallery[default_crop_position]" value="center,top" title="Center, Top" <?php checked( 'center,top', $current_position ) ?>/>
102
+ <input type="radio" name="foogallery[default_crop_position]" value="right,top" title="Right, Top" <?php checked( 'right,top', $current_position ) ?>/><br/>
103
+ <input type="radio" name="foogallery[default_crop_position]" value="left,center" title="Left, Center" <?php checked( 'left,center', $current_position ) ?>/>
104
+ <input type="radio" name="foogallery[default_crop_position]" value="center,center" title="Center, Center" <?php checked( 'center,center', $current_position ) ?>/>
105
+ <input type="radio" name="foogallery[default_crop_position]" value="right,center" title="Right, Center" <?php checked( 'right,center', $current_position ) ?>/><br/>
106
+ <input type="radio" name="foogallery[default_crop_position]" value="left,bottom" title="Left, Bottom" <?php checked( 'left,bottom', $current_position ) ?>/>
107
+ <input type="radio" name="foogallery[default_crop_position]" value="center,bottom" title="Center, Bottom" <?php checked( 'center,bottom', $current_position ) ?>/>
108
+ <input type="radio" name="foogallery[default_crop_position]" value="right,bottom" title="Right, Bottom" <?php checked( 'right,bottom', $current_position ) ?>/>
109
+ </div>
110
+ <?php }
111
+ }
112
+
113
+ /**
114
+ * Return the default crop position
115
+ *
116
+ * @param $default
117
+ *
118
+ * @return mixed
119
+ */
120
+ function default_crop_position() {
121
+ $crop_position = foogallery_get_setting( 'default_crop_position', self::CROP_POSITION_DEFAULT );
122
+ return $crop_position;
123
+ }
124
+
125
+ /**
126
+ * Adds a back end for selecting the crop position of images.
127
+ *
128
+ * @access public
129
+ *
130
+ * @param array $fields
131
+ * @param array $post
132
+ * @return $post
133
+ */
134
+ function media_form_crop_position( $fields, $post ) {
135
+
136
+ if ( !foogallery_thumb_active_engine()->has_local_cache() ) {
137
+ return $fields;
138
+ }
139
+
140
+ if ( ! wp_attachment_is_image( $post->ID ) ) {
141
+ return $fields;
142
+ }
143
+
144
+ $crop_position = $this->get_crop_position_from_attachment( $post->ID );
145
+
146
+ $html = '<style>#foogallery_crop_pos { padding: 5px; } #foogallery_crop_pos input { margin: 5px; width: auto; }</style>';
147
+ $html .= '<div id="foogallery_crop_pos">';
148
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="left,top" title="Left, Top" ' . checked( 'left,top', $crop_position, false ) . '/>';
149
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="center,top" title="Center, Top" ' . checked( 'center,top', $crop_position, false ) . '/>';
150
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="right,top" title="Right, Top" ' . checked( 'right,top', $crop_position, false ) . '/><br/>';
151
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="left,center" title="Left, Center" ' . checked( 'left,center', $crop_position, false ) . '/>';
152
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="center,center" title="Center, Center"' . checked( 'center,center', $crop_position, false ) . '/>';
153
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="right,center" title="Right, Center" ' . checked( 'right,center', $crop_position, false ) . '/><br/>';
154
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="left,bottom" title="Left, Bottom" ' . checked( 'left,bottom', $crop_position, false ) . '/>';
155
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="center,bottom" title="Center, Bottom" ' . checked( 'center,bottom', $crop_position, false ) . '/>';
156
+ $html .= '<input type="radio" name="attachments[' . $post->ID . '][foogallery_crop_pos]" value="right,bottom" title="Right, Bottom" ' . checked( 'right,bottom', $crop_position, false ) . '/>';
157
+ $html .= '</div>';
158
+
159
+ $fields['crop-from-position'] = array(
160
+ 'label' => __( 'Crop Position', 'foogallery' ),
161
+ 'input' => 'html',
162
+ 'html' => $html
163
+ );
164
+
165
+ return $fields;
166
+ }
167
+
168
+ /**
169
+ * Gets the crop position from the attachment post meta, and defaults to what is set in settings
170
+ *
171
+ * @param $attachment_id
172
+ *
173
+ * @return mixed|string
174
+ */
175
+ private function get_crop_position_from_attachment( $attachment_id ) {
176
+ //first try to get the legacy value using the old key
177
+ $crop_postion = get_post_meta( $attachment_id, self::CROP_POSITION_META_KEY_LEGACY, true );
178
+
179
+ //check if we have a legacy value saved, so migrate to the new
180
+ if ( $crop_postion ) {
181
+ //remove the old post meta
182
+ delete_post_meta( $attachment_id, self::CROP_POSITION_META_KEY_LEGACY );
183
+
184
+ //add new post meta with the correct key
185
+ update_post_meta( $attachment_id, self::CROP_POSITION_META_KEY, $crop_postion );
186
+ } else {
187
+ $current_position = get_post_meta( $attachment_id, self::CROP_POSITION_META_KEY, true );
188
+ }
189
+
190
+ if ( !$current_position ) {
191
+ $current_position = $this->default_crop_position();
192
+ }
193
+
194
+ return $current_position;
195
+ }
196
+
197
+ /**
198
+ * wpthumb_media_form_crop_position_save function.
199
+ *
200
+ * Saves crop position in post meta.
201
+ *
202
+ * @access public
203
+ *
204
+ * @param array $post
205
+ * @param array $attachment
206
+ * @return $post
207
+ */
208
+ function media_form_crop_position_save( $post, $attachment ) {
209
+
210
+ if ( !foogallery_thumb_active_engine()->has_local_cache() ) {
211
+ return $post;
212
+ }
213
+
214
+ if ( ! isset( $attachment['foogallery_crop_pos'] ) ) {
215
+ return $post;
216
+ }
217
+
218
+ if ( $attachment['foogallery_crop_pos'] == $this->default_crop_position() ) {
219
+ delete_post_meta( $post['ID'], self::CROP_POSITION_META_KEY );
220
+ } else {
221
+ update_post_meta( $post['ID'], self::CROP_POSITION_META_KEY, $attachment['foogallery_crop_pos'] );
222
+ }
223
+
224
+ return $post;
225
+ }
226
+ }
227
+ }
includes/class-foogallery-default-crop-position.php DELETED
@@ -1,80 +0,0 @@
1
- <?php
2
- /**
3
- * Class to provide a way to override the default attachment crop position. Handy if you want to override the default of center,center
4
- * Date: 19/02/2018
5
- *
6
- * @since 1.4.18
7
- */
8
- if ( ! class_exists( 'FooGallery_Default_Crop_Position' ) ) {
9
-
10
- class FooGallery_Default_Crop_Position {
11
-
12
- function __construct() {
13
- add_filter( 'foogallery_admin_settings_override', array( $this, 'add_default_crop_position_setting' ) );
14
- add_action( 'foogallery_admin_settings_custom_type_render_setting', array( $this, 'render_crop_position_setting' ) );
15
- add_filter( 'wpthumb_default_crop_position', array( $this, 'override_default_crop_position' ) );
16
- }
17
-
18
- /**
19
- * Adds the crop position setting to the settings array
20
- *
21
- * @param $settings
22
- *
23
- * @return mixed
24
- */
25
- function add_default_crop_position_setting( $settings ) {
26
- $just_settings = $settings['settings'];
27
- $position = 0;
28
- //find the position of the 'thumb_jpeg_quality' setting
29
- foreach( $just_settings as $setting ) {
30
- $position++;
31
- if ( 'thumb_jpeg_quality' === $setting['id'] ) {
32
- break;
33
- }
34
- }
35
-
36
- $new_settings[] = array(
37
- 'id' => 'default_crop_position',
38
- 'title' => __( 'Default Crop Position', 'foogallery' ),
39
- 'desc' => __( 'The default crop position when resizing thumbnails.', 'foogallery' ),
40
- 'type' => 'crop',
41
- 'default' => 'center,center',
42
- 'tab' => 'thumb'
43
- );
44
-
45
- array_splice( $just_settings, $position, 0, $new_settings );
46
-
47
- $settings['settings'] = $just_settings;
48
-
49
- return $settings;
50
- }
51
-
52
- /**
53
- * Render the custom crop position to the settings page
54
- *
55
- * @param array $args
56
- */
57
- function render_crop_position_setting( $args ) {
58
- if ( 'crop' === $args['type'] ) {
59
- $current_position = foogallery_get_setting( 'default_crop_position', 'center,center'); ?>
60
- <style>.foogallery_crop_pos input { margin: 5px !important; width: auto; }</style>
61
- <div class="foogallery_crop_pos">
62
- <input type="radio" name="foogallery[default_crop_position]" value="left,top" title="Left, Top" <?php checked( 'left,top', $current_position ) ?>/>
63
- <input type="radio" name="foogallery[default_crop_position]" value="center,top" title="Center, Top" <?php checked( 'center,top', $current_position ) ?>/>
64
- <input type="radio" name="foogallery[default_crop_position]" value="right,top" title="Right, Top" <?php checked( 'right,top', $current_position ) ?>/><br/>
65
- <input type="radio" name="foogallery[default_crop_position]" value="left,center" title="Left, Center" <?php checked( 'left,center', $current_position ) ?>/>
66
- <input type="radio" name="foogallery[default_crop_position]" value="center,center" title="Center, Center" <?php checked( 'center,center', $current_position ) ?>/>
67
- <input type="radio" name="foogallery[default_crop_position]" value="right,center" title="Right, Center" <?php checked( 'right,center', $current_position ) ?>/><br/>
68
- <input type="radio" name="foogallery[default_crop_position]" value="left,bottom" title="Left, Bottom" <?php checked( 'left,bottom', $current_position ) ?>/>
69
- <input type="radio" name="foogallery[default_crop_position]" value="center,bottom" title="Center, Bottom" <?php checked( 'center,bottom', $current_position ) ?>/>
70
- <input type="radio" name="foogallery[default_crop_position]" value="right,bottom" title="Right, Bottom" <?php checked( 'right,bottom', $current_position ) ?>/>
71
- </div>
72
- <?php }
73
- }
74
-
75
- function override_default_crop_position( $default ) {
76
- $crop_position = foogallery_get_setting( 'default_crop_position', 'center,center');
77
- return $crop_position;
78
- }
79
- }
80
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-thumbnails.php CHANGED
@@ -8,10 +8,9 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
8
  class FooGallery_Thumbnails {
9
 
10
  function __construct() {
11
- //generate thumbs using WPThumb
12
  add_filter( 'foogallery_attachment_resize_thumbnail', array( $this, 'resize' ), 10, 3 );
13
 
14
- add_filter( 'foogallery_test_thumb_url', array( $this, 'find_first_image_in_media_library' ) );
15
 
16
  add_filter( 'foogallery_thumbnail_resize_args', array( $this, 'check_for_force_original_thumb') );
17
  }
@@ -35,7 +34,7 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
35
  'height' => 0,
36
  'crop' => true,
37
  'jpeg_quality' => foogallery_thumbnail_jpeg_quality(),
38
- 'thumb_resize_animations' => foogallery_get_setting( 'thumb_resize_animations' ),
39
  'foogallery_attachment_id'=> $thumbnail_object->ID
40
  );
41
 
@@ -101,14 +100,6 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
101
  }
102
  }
103
 
104
- if ( $thumbnail_object->ID > 0 ) {
105
- $crop_from_position = get_post_meta( $thumbnail_object->ID, 'wpthumb_crop_pos', true );
106
-
107
- if ( !empty( $crop_from_position ) ) {
108
- $args['crop_from_position'] = $crop_from_position;
109
- }
110
- }
111
-
112
  //remove invalid resize args
113
  if ( array_key_exists( 'height', $args ) && 0 === $args['height'] ) {
114
  unset( $args['height'] );
@@ -122,15 +113,19 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
122
  //check if we must upscale smaller images
123
  if ( 'on' === foogallery_get_setting( 'thumb_resize_upscale_small' ) ) {
124
  $force_resize = true;
125
- $colors = foogallery_rgb_to_color_array( foogallery_get_setting( 'thumb_resize_upscale_small_color', '' ) );
126
- $args['background_fill'] = sprintf( "%03d%03d%03d000", $colors[0], $colors[1], $colors[2] );
 
 
 
 
127
  }
128
  }
129
 
130
  //do some checks to see if the image is smaller
131
  if ( $force_resize || $this->should_resize( $thumbnail_object, $args ) ) {
132
  //save the generated thumb url to a global so that we can use it later if needed
133
- $foogallery_last_generated_thumb_url = wpthumb( $original_image_src, $args );
134
  } else {
135
  $foogallery_last_generated_thumb_url = apply_filters('foogallery_thumbnail_resize_small_image', $original_image_src, $args );
136
  }
@@ -159,6 +154,12 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
159
  }
160
 
161
  function run_thumbnail_generation_tests() {
 
 
 
 
 
 
162
  $test_image_url = foogallery_test_thumb_url();
163
 
164
  //next, generate a thumbnail
@@ -169,19 +170,19 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
169
  'jpeg_quality' => foogallery_thumbnail_jpeg_quality()
170
  );
171
 
172
- //first, clear any previous cached files
173
- $thumb = new WP_Thumb( $test_image_url, $test_args );
174
- wpthumb_rmdir_recursive( $thumb->getCacheFileDirectory() );
 
 
175
 
176
- $test_thumb = new WP_Thumb( $test_image_url, $test_args );
177
- $generated_thumb = $test_thumb->returnImage();
178
  $success = $test_image_url !== $generated_thumb;
179
  $file_info = wp_check_filetype( $test_image_url );
180
 
181
  $test_results = array(
182
  'success' => $success,
183
  'thumb' => $generated_thumb,
184
- 'error' => $test_thumb->errored() ? $test_thumb->error : '',
185
  'file_info' => $file_info
186
  );
187
 
@@ -190,24 +191,12 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
190
  return $test_results;
191
  }
192
 
193
- function find_first_image_in_media_library( $test_thumb_url ) {
194
  if ( 'on' !== foogallery_get_setting( 'override_thumb_test', false ) ) {
195
- //try the first 10 attachments from the media library
196
- $args = array(
197
- 'post_type' => 'attachment',
198
- 'post_mime_type' => 'image',
199
- 'post_status' => 'any',
200
- 'numberposts' => 10,
201
- 'orderby' => 'date',
202
- 'order' => 'ASC'
203
- );
204
- $query_images = new WP_Query( $args );
205
- foreach ( $query_images->posts as $image ) {
206
- $image_url = wp_get_attachment_url( $image->ID );
207
 
208
- if ( $this->image_file_exists( $image_url ) ) {
209
- return $image_url;
210
- }
211
  }
212
  }
213
 
@@ -216,13 +205,35 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
216
  return 'https://s3.amazonaws.com/foocdn/test.jpg';
217
  }
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  /**
220
  * Check if a remote image file exists.
221
  *
222
  * @param string $url The url to the remote image.
223
  * @return bool Whether the remote image exists.
224
  */
225
- function image_file_exists( $url ) {
226
  $response = wp_remote_head( $url );
227
  return 200 === wp_remote_retrieve_response_code( $response );
228
  }
8
  class FooGallery_Thumbnails {
9
 
10
  function __construct() {
 
11
  add_filter( 'foogallery_attachment_resize_thumbnail', array( $this, 'resize' ), 10, 3 );
12
 
13
+ add_filter( 'foogallery_test_thumb_url', array( $this, 'override_test_thumb_url' ) );
14
 
15
  add_filter( 'foogallery_thumbnail_resize_args', array( $this, 'check_for_force_original_thumb') );
16
  }
34
  'height' => 0,
35
  'crop' => true,
36
  'jpeg_quality' => foogallery_thumbnail_jpeg_quality(),
37
+ 'thumb_resize_animations' => true,
38
  'foogallery_attachment_id'=> $thumbnail_object->ID
39
  );
40
 
100
  }
101
  }
102
 
 
 
 
 
 
 
 
 
103
  //remove invalid resize args
104
  if ( array_key_exists( 'height', $args ) && 0 === $args['height'] ) {
105
  unset( $args['height'] );
113
  //check if we must upscale smaller images
114
  if ( 'on' === foogallery_get_setting( 'thumb_resize_upscale_small' ) ) {
115
  $force_resize = true;
116
+ $color = foogallery_get_setting( 'thumb_resize_upscale_small_color', '' );
117
+ if ( $color !== 'auto' && $color !== 'transparent' ) {
118
+ $colors = foogallery_rgb_to_color_array( $color );
119
+ $color = sprintf( "%03d%03d%03d000", $colors[0], $colors[1], $colors[2] );
120
+ }
121
+ $args['background_fill'] = $color;
122
  }
123
  }
124
 
125
  //do some checks to see if the image is smaller
126
  if ( $force_resize || $this->should_resize( $thumbnail_object, $args ) ) {
127
  //save the generated thumb url to a global so that we can use it later if needed
128
+ $foogallery_last_generated_thumb_url = foogallery_thumb( $original_image_src, $args );
129
  } else {
130
  $foogallery_last_generated_thumb_url = apply_filters('foogallery_thumbnail_resize_small_image', $original_image_src, $args );
131
  }
154
  }
155
 
156
  function run_thumbnail_generation_tests() {
157
+ if ( !foogallery_thumb_active_engine()->requires_thumbnail_generation_tests() ) {
158
+ return array(
159
+ 'success' => true
160
+ );
161
+ }
162
+
163
  $test_image_url = foogallery_test_thumb_url();
164
 
165
  //next, generate a thumbnail
170
  'jpeg_quality' => foogallery_thumbnail_jpeg_quality()
171
  );
172
 
173
+ //first, clear any previous cached files
174
+ $engine = foogallery_thumb_active_engine();
175
+ $engine->clear_local_cache_for_file( $test_image_url );
176
+
177
+ $generated_thumb = $engine->generate( $test_image_url, $test_args );
178
 
 
 
179
  $success = $test_image_url !== $generated_thumb;
180
  $file_info = wp_check_filetype( $test_image_url );
181
 
182
  $test_results = array(
183
  'success' => $success,
184
  'thumb' => $generated_thumb,
185
+ 'error' => $engine->get_last_error(),
186
  'file_info' => $file_info
187
  );
188
 
191
  return $test_results;
192
  }
193
 
194
+ function override_test_thumb_url( $test_thumb_url ) {
195
  if ( 'on' !== foogallery_get_setting( 'override_thumb_test', false ) ) {
196
+ $image_url = $this->find_first_image_in_media_library();
 
 
 
 
 
 
 
 
 
 
 
197
 
198
+ if ( $image_url !== false ) {
199
+ return $image_url;
 
200
  }
201
  }
202
 
205
  return 'https://s3.amazonaws.com/foocdn/test.jpg';
206
  }
207
 
208
+ static function find_first_image_in_media_library() {
209
+ //try the first 10 attachments from the media library
210
+ $args = array(
211
+ 'post_type' => 'attachment',
212
+ 'post_mime_type' => 'image',
213
+ 'post_status' => 'any',
214
+ 'numberposts' => 10,
215
+ 'orderby' => 'date',
216
+ 'order' => 'ASC'
217
+ );
218
+ $query_images = new WP_Query( $args );
219
+ foreach ( $query_images->posts as $image ) {
220
+ $image_url = wp_get_attachment_url( $image->ID );
221
+
222
+ if ( self::image_file_exists( $image_url ) ) {
223
+ return $image_url;
224
+ }
225
+ }
226
+
227
+ return false;
228
+ }
229
+
230
  /**
231
  * Check if a remote image file exists.
232
  *
233
  * @param string $url The url to the remote image.
234
  * @return bool Whether the remote image exists.
235
  */
236
+ static function image_file_exists( $url ) {
237
  $response = wp_remote_head( $url );
238
  return 200 === wp_remote_retrieve_response_code( $response );
239
  }
includes/class-wpthumb-enhancements.php DELETED
@@ -1,70 +0,0 @@
1
- <?php
2
- /**
3
- * WPThumb Enhancements Class
4
- * Date: 7 Nov 2016
5
- *
6
- * Some themes include a filter to override the ORDER of the image editors to be used,
7
- * so that the GD library is used as a preference over the Imagick library.
8
- * This is acceptable, but WPThumb requires it's own overrides of the WP_Image_Editor_GD
9
- * and WP_Image_Editor_Imagick classes (set in wpthumb.php 'wpthumb_add_image_editors'
10
- * function). An example of this filter code is:
11
- *
12
- * add_filter( 'wp_image_editors', 'change_graphic_lib' );
13
- * function change_graphic_lib($array) {
14
- * return array( 'WP_Image_Editor_GD', 'WP_Image_Editor_Imagick' );
15
- * }
16
- *
17
- * The theme's filter runs after the WPThumb filter, so the override classes needed
18
- * by WPThumb are ignored. This stops WPThumb from working altogether. To get around
19
- * this we need to override the image editors later (priority 999) and "force" the
20
- * usage of the WPThumb override classes, while still preserving the order set by the
21
- * theme author, or server administrator.
22
- *
23
- * The hosting provider's decision to use GD over Imagick is usually due to a timeout
24
- * that occurs when large images are uploaded to the media library. The PHP setting
25
- * for memory on the server could be too low, and this causes Imagick to timeout.
26
- * Switching to GD usually fixes the problem, without needing to change memory limits.
27
- *
28
- */
29
- if ( ! class_exists( 'FooGallery_WPThumb_Enhancements' ) ) {
30
-
31
- class FooGallery_WPThumb_Enhancements {
32
-
33
- function __construct() {
34
- add_filter( 'wp_image_editors', array( $this, 'override_image_editors' ), 999 );
35
- }
36
-
37
- /**
38
- * Overrides the editors to make sure the WPThumb editors are included
39
- *
40
- * @param $editors
41
- * @return array
42
- */
43
- function override_image_editors($editors) {
44
-
45
- $wpthumb_editors = array();
46
-
47
- //replace the default image editors with the WPThumb image editors, so that WPThumb continues to work
48
- foreach ($editors as $editor) {
49
- switch ($editor) {
50
- case 'WP_Image_Editor_Imagick':
51
- $wpthumb_editors[] = 'WP_Thumb_Image_Editor_Imagick';
52
- break;
53
- case 'WP_Image_Editor_GD':
54
- $wpthumb_editors[] = 'WP_Thumb_Image_Editor_GD';
55
- break;
56
- default:
57
- $wpthumb_editors[] = $editor;
58
- }
59
- }
60
-
61
- //Make sure the order is correct
62
- if ( foogallery_get_setting( 'force_gd_library', false ) ) {
63
- array_splice( $wpthumb_editors, 0, 0, array('WP_Thumb_Image_Editor_GD') );
64
- }
65
-
66
- //make sure we have a unique list of editors
67
- return array_unique( $wpthumb_editors );
68
- }
69
- }
70
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions.php CHANGED
@@ -138,7 +138,6 @@ function foogallery_get_default( $key, $default = false )
138
  'gallery_permalink' => 'gallery',
139
  'lightbox' => 'none',
140
  'thumb_jpeg_quality' => '80',
141
- 'thumb_resize_animations' => true,
142
  'gallery_sorting' => '',
143
  'datasource' => 'media_library',
144
  );
@@ -1535,6 +1534,23 @@ function foogallery_get_language_array_value( $setting_key, $default )
1535
  return false;
1536
  }
1537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1538
  /**
1539
  * Returns a formatted date
1540
  *
@@ -1559,3 +1575,69 @@ function foogallery_format_date( $timestamp, $format = null )
1559
  }
1560
 
1561
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  'gallery_permalink' => 'gallery',
139
  'lightbox' => 'none',
140
  'thumb_jpeg_quality' => '80',
 
141
  'gallery_sorting' => '',
142
  'datasource' => 'media_library',
143
  );
1534
  return false;
1535
  }
1536
 
1537
+ /**
1538
+ * Safely returns the WP Filesystem instance for use in FooGallery
1539
+ *
1540
+ * @return WP_Filesystem_Base
1541
+ */
1542
+ function foogallery_wp_filesystem()
1543
+ {
1544
+ global $wp_filesystem ;
1545
+ if ( !function_exists( 'WP_Filesystem' ) ) {
1546
+ require_once ABSPATH . 'wp-admin/includes/file.php';
1547
+ }
1548
+ if ( !WP_Filesystem( true ) ) {
1549
+ return false;
1550
+ }
1551
+ return $wp_filesystem;
1552
+ }
1553
+
1554
  /**
1555
  * Returns a formatted date
1556
  *
1575
  }
1576
 
1577
  }
1578
+
1579
+ /**
1580
+ * functions related to thumbnail generation within FooGallery
1581
+ */
1582
+ /**
1583
+ * Returns the array of available engines
1584
+ *
1585
+ * @return array
1586
+ */
1587
+ function foogallery_thumb_available_engines()
1588
+ {
1589
+ $engines = array(
1590
+ 'default' => array(
1591
+ 'label' => __( 'Default', 'foogallery' ),
1592
+ 'description' => __( 'The default engine used to generate locally cached thumbnails.', 'foogallery' ),
1593
+ 'class' => 'FooGallery_Thumb_Engine_Default',
1594
+ ),
1595
+ );
1596
+ if ( foogallery_is_debug() ) {
1597
+ $engines['dummy'] = array(
1598
+ 'label' => __( 'Dummy', 'foogallery' ),
1599
+ 'description' => __( 'A dummy thumbnail engine that can be used for testing. (uses dummyimage.com)', 'foogallery' ),
1600
+ 'class' => 'FooGallery_Thumb_Engine_Dummy',
1601
+ );
1602
+ }
1603
+ return apply_filters( 'foogallery_thumb_available_engines', $engines );
1604
+ }
1605
+
1606
+ /**
1607
+ * Returns the active thumb engine, based on settings
1608
+ *
1609
+ * @return FooGallery_Thumb_Engine
1610
+ */
1611
+ function foogallery_thumb_active_engine()
1612
+ {
1613
+ global $foogallery_thumb_engine ;
1614
+ //if we already have an engine, return it early
1615
+ if ( isset( $foogallery_thumb_engine ) && is_a( $foogallery_thumb_engine, 'FooGallery_Thumb_Engine' ) ) {
1616
+ return $foogallery_thumb_engine;
1617
+ }
1618
+ $engine = foogallery_get_setting( 'thumb_engine', 'default' );
1619
+ $engines = foogallery_thumb_available_engines();
1620
+
1621
+ if ( array_key_exists( $engine, $engines ) ) {
1622
+ $active_engine = $engines[$engine];
1623
+ $foogallery_thumb_engine = new $active_engine['class']();
1624
+ } else {
1625
+ $foogallery_thumb_engine = new FooGallery_Thumb_Engine_Default();
1626
+ }
1627
+
1628
+ return $foogallery_thumb_engine;
1629
+ }
1630
+
1631
+ /**
1632
+ * Resizes a given image using the active thumb engine.
1633
+ *
1634
+ * @param $url
1635
+ * @param array $args
1636
+ *
1637
+ * @return string|void (string) url to the image
1638
+ */
1639
+ function foogallery_thumb( $url, $args = array() )
1640
+ {
1641
+ $engine = foogallery_thumb_active_engine();
1642
+ return $engine->generate( $url, $args );
1643
+ }
includes/includes.php CHANGED
@@ -17,13 +17,9 @@ require_once( FOOGALLERY_PATH . 'includes/class-foogallery-upgrade.php' );
17
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-widget.php' );
18
  require_once( FOOGALLERY_PATH . 'gutenberg/class-foogallery-gutenberg.php' );
19
 
20
- //check for WPThumb, include.
21
- if ( ! class_exists( 'WP_Thumb' ) ) {
22
- require_once( FOOGALLERY_PATH . 'includes/WPThumb/wpthumb.php' );
23
- //do not let WPThumb override build-in WordPress functions like the_post_thumbnail
24
- remove_filter( 'image_downsize', 'wpthumb_post_image', 99 );
25
- }
26
- require_once( FOOGALLERY_PATH . 'includes/class-wpthumb-enhancements.php' );
27
 
28
  //include bundled extensions
29
  require_once( FOOGALLERY_PATH . 'extensions/albums/class-albums-extension.php' );
@@ -47,7 +43,7 @@ require_once( FOOGALLERY_PATH . 'includes/class-foogallery-lazyload.php' );
47
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-paging.php' );
48
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-attachment-custom-class.php' );
49
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-extensions-compatibility.php' );
50
- require_once( FOOGALLERY_PATH . 'includes/class-foogallery-default-crop-position.php' );
51
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-force-https.php' );
52
 
53
  //Datasource includes
@@ -59,7 +55,6 @@ if ( is_admin() ) {
59
  require_once( FOOGALLERY_PATH . 'includes/admin/class-admin.php' );
60
  require_once( FOOGALLERY_PATH . 'includes/admin/class-extensions.php' );
61
  require_once( FOOGALLERY_PATH . 'includes/admin/class-settings.php' );
62
- require_once( FOOGALLERY_PATH . 'includes/admin/class-settings-image-optimization.php' );
63
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-editor.php' );
64
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-metaboxes.php' );
65
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-metabox-items.php' );
17
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-widget.php' );
18
  require_once( FOOGALLERY_PATH . 'gutenberg/class-foogallery-gutenberg.php' );
19
 
20
+ //include built-in thumbnail generation files
21
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/includes.php' );
22
+
 
 
 
 
23
 
24
  //include bundled extensions
25
  require_once( FOOGALLERY_PATH . 'extensions/albums/class-albums-extension.php' );
43
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-paging.php' );
44
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-attachment-custom-class.php' );
45
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-extensions-compatibility.php' );
46
+ require_once( FOOGALLERY_PATH . 'includes/class-foogallery-crop-position.php' );
47
  require_once( FOOGALLERY_PATH . 'includes/class-foogallery-force-https.php' );
48
 
49
  //Datasource includes
55
  require_once( FOOGALLERY_PATH . 'includes/admin/class-admin.php' );
56
  require_once( FOOGALLERY_PATH . 'includes/admin/class-extensions.php' );
57
  require_once( FOOGALLERY_PATH . 'includes/admin/class-settings.php' );
 
58
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-editor.php' );
59
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-metaboxes.php' );
60
  require_once( FOOGALLERY_PATH . 'includes/admin/class-gallery-metabox-items.php' );
includes/thumbs/class-foogallery-thumb-engine.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for the thumbnail engine
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Engine' ) ) {
6
+
7
+ abstract class FooGallery_Thumb_Engine {
8
+
9
+ /**
10
+ * Does any initilization needed for the engine
11
+ */
12
+ abstract function init();
13
+
14
+ /**
15
+ * Generates a thumbnail for an image based on arguments
16
+ *
17
+ * @param $url
18
+ * @param array $args
19
+ *
20
+ * @return string
21
+ */
22
+ abstract function generate( $url, $args = array() );
23
+
24
+ /**
25
+ * Does the engine use a local cache to store thumbnails
26
+ * @return bool
27
+ */
28
+ abstract function has_local_cache();
29
+
30
+ /**
31
+ * Clears the local cach for a file
32
+ * @param $file
33
+ */
34
+ abstract function clear_local_cache_for_file( $file );
35
+
36
+ /**
37
+ * Returns the last error encountered when trying to generate a thumbnail
38
+ * @return mixed
39
+ */
40
+ abstract function get_last_error();
41
+
42
+ /**
43
+ * Returns true if the engine utilizes WordPress Image Editors under the hood
44
+ * By default, if the engine has a local cache, then they would also use image editors
45
+ *
46
+ * @return bool
47
+ */
48
+ function uses_image_editors() {
49
+ return $this->has_local_cache();
50
+ }
51
+
52
+ /**
53
+ * Returns true if the engine requires thumb generation tests to be performed
54
+ * By default, if the engine has a local cache, then they would also use require tests
55
+ *
56
+ * @return bool
57
+ */
58
+ function requires_thumbnail_generation_tests() {
59
+ return $this->has_local_cache();
60
+ }
61
+ }
62
+ }
includes/thumbs/class-foogallery-thumb-manager.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class that managers all thumbnail generation within FooGallery
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Manager' ) ) {
6
+
7
+ class FooGallery_Thumb_Manager {
8
+
9
+ function __construct() {
10
+ add_action( 'plugins_loaded', array( $this, 'init_active_engine' ) );
11
+ }
12
+
13
+ /**
14
+ * Make sure the active thumb engine initializes
15
+ */
16
+ function init_active_engine() {
17
+ $engine = foogallery_thumb_active_engine();
18
+ $engine->init();
19
+ }
20
+ }
21
+ }
includes/thumbs/default/class-foogallery-thumb-engine-default.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for the default thumbnail engine in FooGallery
5
+ */
6
+ if ( ! class_exists( 'FooGallery_Thumb_Engine_Default' ) ) {
7
+
8
+ class FooGallery_Thumb_Engine_Default extends FooGallery_Thumb_Engine {
9
+
10
+ /**
11
+ * The last error that was encounted
12
+ * @var mixed
13
+ */
14
+ private $last_error;
15
+
16
+ public function init() {
17
+ add_filter( 'wp_image_editors', array( $this, 'override_image_editors' ), 999 );
18
+ add_filter( 'deleted_post', array( $this, 'delete_cache_folder_for_attachment' ), 10, 2 );
19
+ add_action( 'foogallery_admin_menu_after', array( $this, 'add_test_thumb_menu' ) );
20
+
21
+ //add background fill functionality
22
+ new FooGallery_Thumb_Generator_Background_Fill();
23
+ }
24
+
25
+ /**
26
+ * Registers the test thumb menu and page
27
+ */
28
+ function add_test_thumb_menu() {
29
+ //register the menu and page
30
+ foogallery_add_submenu_page( 'Thumbnail Generation Tests', 'manage_options', 'foogallery_thumb_test', array( $this, 'render_thumb_test_page' ) );
31
+
32
+ //hide the menu, but still keep the page registered so it can be rendered
33
+ remove_submenu_page( foogallery_admin_menu_parent_slug(), 'foogallery_thumb_test' );
34
+ }
35
+
36
+ /**
37
+ * renders a bunch of thumb tests
38
+ */
39
+ function render_thumb_test_page() {
40
+ echo '<h2>Thumbnail Test Page</h2>';
41
+
42
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test3', 'PNG+No extension Resize to 30x30', 30, 30 );
43
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test1.png', 'PNG Resize to 50x50' );
44
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test2.png?test=1&another=true', 'PNG+Querystring Resize to 40x40', 40, 40 );
45
+
46
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test4.gif', 'GIF Resize to 50x50' );
47
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test5.jpg', 'JPG Resize to 50x50' );
48
+ $this->render_thumb_test_html( FOOGALLERY_URL . 'includes/thumbs/default/tests/test6.bmp', 'BMP Resize to 50x50' );
49
+
50
+ $this->render_thumb_test_html( 'https://s3.amazonaws.com/foocdn/test.jpg', 'Remote Resize to 50x50' );
51
+ $this->render_thumb_test_html( FooGallery_Thumbnails::find_first_image_in_media_library(), 'Media Resize to 50x50' );
52
+
53
+ $this->render_thumb_test_html( 'https://fooplugins.s3.amazonaws.com/test.php', 'Remote test for non image' );
54
+ }
55
+
56
+ /**
57
+ * Renders a single thumb test
58
+ *
59
+ * @param $url
60
+ * @param $title
61
+ * @param int $width
62
+ * @param int $height
63
+ */
64
+ function render_thumb_test_html( $url, $title, $width = 50, $height = 50) {
65
+ if ( $url === false ) {
66
+ return;
67
+ }
68
+
69
+ $engine = foogallery_thumb_active_engine();
70
+
71
+ //always clear the cache for the file
72
+ $engine->clear_local_cache_for_file( $url );
73
+
74
+ $resize_url = $engine->generate( $url, array(
75
+ 'width' => $width,
76
+ 'height' => $height,
77
+ 'crop' => true
78
+ ) );
79
+
80
+ echo '<h3>' . $title . '</h3>';
81
+ echo 'original : <code>' . $url . '</code><br />';
82
+ echo 'result : <code>' . $resize_url . '</code><br /><br />';
83
+
84
+ if ( isset( $engine->last_error ) ) {
85
+ print_r( $engine->last_error );
86
+ } else {
87
+ echo '<img src="' . $url . '" />';
88
+ echo '&nbsp;&nbsp;&nbsp;→→→&nbsp;&nbsp;&nbsp;';
89
+ echo '<img src="' . $resize_url . '" />';
90
+ }
91
+
92
+ echo '<br />';
93
+ }
94
+
95
+ /**
96
+ * The default engine uses a local cache to store thumbnails
97
+ *
98
+ * @return bool
99
+ */
100
+ public function has_local_cache() {
101
+ return true;
102
+ }
103
+
104
+ /**
105
+ * Generates the thumbnail and returns the thumb URL
106
+ *
107
+ * @param $url
108
+ * @param array $args
109
+ *
110
+ * @return string|void
111
+ */
112
+ function generate( $url, $args = array() ) {
113
+ $generator = new FooGallery_Thumb_Generator( $url, $args );
114
+ $result = $generator->generate();
115
+ $this->last_error = $generator->error();
116
+ return $result;
117
+ }
118
+
119
+ /**
120
+ * Returns the last error that was encountered
121
+ * @return mixed
122
+ */
123
+ function get_last_error() {
124
+ return $this->last_error;
125
+ }
126
+
127
+ /**
128
+ * Delete the cache directory for a file
129
+ *
130
+ * @param $file
131
+ */
132
+ public function clear_local_cache_for_file( $file ) {
133
+ $thumb = new FooGallery_Thumb_Generator( $file );
134
+ $directory = $thumb->get_cache_file_directory();
135
+
136
+ if ( false === $directory ) {
137
+ return;
138
+ }
139
+
140
+ //use the WP FileSystem to remove the folder recursively
141
+ $fs = foogallery_wp_filesystem();
142
+ if ( $fs !== false ) {
143
+ $fs->rmdir( $directory, true );
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Overrides the editors to make sure the FooGallery thumb editors are included
149
+ *
150
+ * @param $editors
151
+ * @return array
152
+ */
153
+ function override_image_editors( $editors ) {
154
+
155
+ require_once( FOOGALLERY_PATH . '/includes/thumbs/default/class-foogallery-thumb-image-editor-gd.php' );
156
+ require_once( FOOGALLERY_PATH . '/includes/thumbs/default/class-foogallery-thumb-image-editor-imagick.php' );
157
+
158
+ $image_editors = array();
159
+
160
+ //replace the default image editors with the FooGallery Thumb image editors
161
+ foreach ( $editors as $editor ) {
162
+ switch ( $editor ) {
163
+ case 'WP_Image_Editor_Imagick':
164
+ $image_editors[] = 'FooGallery_Thumb_Image_Editor_Imagick';
165
+ break;
166
+ case 'WP_Image_Editor_GD':
167
+ $image_editors[] = 'FooGallery_Thumb_Image_Editor_GD';
168
+ break;
169
+ default:
170
+ $image_editors[] = $editor;
171
+ }
172
+ }
173
+
174
+ //Make sure the order is correct
175
+ if ( foogallery_get_setting( 'force_gd_library', false ) ) {
176
+ array_splice( $image_editors, 0, 0, array('FooGallery_Thumb_Image_Editor_GD') );
177
+ }
178
+
179
+ //make sure we have a unique list of editors
180
+ return array_unique( $image_editors );
181
+ }
182
+
183
+ /**
184
+ * Hook into deleted_post and delete the associated cache file folder for an attachment
185
+ *
186
+ * @param string $post_id
187
+ *
188
+ * @return string
189
+ */
190
+ function delete_cache_folder_for_attachment( $post_id, $post ) {
191
+ $url = wp_get_attachment_url( $post_id );
192
+
193
+ if ( $url !== false ) {
194
+ $this->clear_local_cache_for_file( $url );
195
+ }
196
+ }
197
+ }
198
+ }
includes/thumbs/default/class-foogallery-thumb-generator-background-fill.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adds background fill functionality to the default FooGallery thumb generator
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Generator_Background_Fill' ) ) {
6
+ class FooGallery_Thumb_Generator_Background_Fill {
7
+
8
+ private $args;
9
+ private $editor;
10
+
11
+ public function __construct() {
12
+ add_filter( 'foogallery_thumb_image_post', array( $this, 'add_background_fill'), 10, 2 );
13
+ }
14
+
15
+ /**
16
+ * @param $editor WP_Image_Editor
17
+ * @param $args array
18
+ *
19
+ * @return WP_Image_Editor
20
+ */
21
+ function add_background_fill( $editor, $args ) {
22
+ // currently only supports GD
23
+ if ( !is_a( $editor, 'FooGallery_Thumb_Image_Editor_GD' ) ) {
24
+ return $editor;
25
+ }
26
+
27
+ $this->editor = $editor;
28
+ $this->args = $args;
29
+
30
+ if ( !array_key_exists( 'background_fill', $args ) ) {
31
+ //get out early if we do not have specific arguments
32
+ return $editor;
33
+ }
34
+
35
+ $color = $this->args['background_fill'];
36
+
37
+ if ( is_null( $color ) ) {
38
+ //get out early if we do not have specific arguments
39
+ return $editor;
40
+ }
41
+
42
+ if ( $color === 'auto' ) {
43
+ $color = $this->get_background_colors();
44
+ } else if ( $color === 'transparent' ) {
45
+ $color = '255255255127';
46
+ }
47
+
48
+ //check for short color
49
+ if ( !is_array( $color ) && strlen( $color ) == 3 ) {
50
+ $color = (float) str_pad( (string) $color, 9, $color ) . '000';
51
+ }
52
+
53
+ //convert to an array if needed
54
+ if ( !is_array( $color ) ) {
55
+ $color = array( 'top' => $color, 'bottom' => $color, 'left' => $color, 'right' => $color );
56
+ }
57
+
58
+ $this->fill_color( $color );
59
+
60
+ return $editor;
61
+ }
62
+
63
+ /**
64
+ * Background fill an image using the provided colors
65
+ *
66
+ * @param array $colors The desired pad colors in RGB format, array should be array( 'top' => '', 'bottom' => '', 'left' => '', 'right' => '' );
67
+ */
68
+ private function fill_color( array $colors ) {
69
+
70
+ $current_size = $this->editor->get_size();
71
+
72
+ $size = array( 'width' => $this->args['width'], 'height' => $this->args['height'] );
73
+
74
+ $offsetLeft = ( $size['width'] - $current_size['width'] ) / 2;
75
+ $offsetTop = ( $size['height'] - $current_size['height'] ) / 2;
76
+
77
+ $new_image = imagecreatetruecolor( $size['width'], $size['height'] );
78
+
79
+ // This is needed to support alpha
80
+ imagesavealpha( $new_image, true );
81
+ imagealphablending( $new_image, false );
82
+
83
+ // Check if we are padding vertically or horizontally
84
+ if ( $current_size['width'] != $size['width'] ) {
85
+
86
+ $colorToPaint = imagecolorallocatealpha( $new_image,
87
+ substr( $colors['left'], 0, 3 ),
88
+ substr( $colors['left'], 3, 3 ),
89
+ substr( $colors['left'], 6, 3 ),
90
+ substr( $colors['left'], 9, 3 ) );
91
+
92
+ // Fill left color
93
+ imagefilledrectangle( $new_image, 0, 0, $offsetLeft, $size['height'], $colorToPaint );
94
+
95
+ $colorToPaint = imagecolorallocatealpha( $new_image,
96
+ substr( $colors['right'], 0, 3 ),
97
+ substr( $colors['right'], 3, 3 ),
98
+ substr( $colors['right'], 6, 3 ),
99
+ substr( $colors['left'], 9, 3 ) );
100
+
101
+ // Fill right color
102
+ imagefilledrectangle( $new_image, $offsetLeft + $current_size['width'], 0, $size['width'], $size['height'], $colorToPaint );
103
+ }
104
+
105
+ if ( $current_size['height'] != $size['height'] ) {
106
+
107
+ $colorToPaint = imagecolorallocatealpha( $new_image,
108
+ substr( $colors['top'], 0, 3 ),
109
+ substr( $colors['top'], 3, 3 ),
110
+ substr( $colors['top'], 6, 3 ),
111
+ substr( $colors['top'], 9, 3 ) );
112
+
113
+ // Fill top color
114
+ imagefilledrectangle( $new_image, 0, 0, $size['width'], $offsetTop - 1, $colorToPaint );
115
+
116
+ $colorToPaint = imagecolorallocatealpha( $new_image,
117
+ substr( $colors['bottom'], 0, 3 ),
118
+ substr( $colors['bottom'], 3, 3 ),
119
+ substr( $colors['bottom'], 6, 3 ),
120
+ substr( $colors['bottom'], 9, 3 ) );
121
+
122
+ // Fill bottom color
123
+ imagefilledrectangle( $new_image, 0, $offsetTop + $current_size['height'], $size['width'], $size['height'], $colorToPaint );
124
+ }
125
+
126
+ imagecopy( $new_image, $this->editor->get_image(), $offsetLeft, $offsetTop, 0, 0, $current_size['width'], $current_size['height'] );
127
+
128
+ $this->editor->update_image( $new_image );
129
+ $this->editor->update_size();
130
+ }
131
+
132
+ /**
133
+ * Return the background colors for the edges of an image
134
+ *
135
+ * @return array
136
+ */
137
+ public function get_background_colors() {
138
+
139
+ $current_size = $this->editor->get_size();
140
+ $midway_x = intval($current_size['width'] / 2);
141
+ $midway_y = intval($current_size['height'] / 2);
142
+
143
+ $coords = array(
144
+ 'top' => array( $midway_x, 0 ),
145
+ 'bottom' => array( $midway_x, $current_size['height'] - 1 ),
146
+ 'left' => array( 0, $midway_y ),
147
+ 'right' => array( $current_size['width'] - 1, $midway_y )
148
+ );
149
+
150
+ $colors = array();
151
+
152
+ foreach ( $coords as $position => $coord ) {
153
+ $c = $this->editor->get_pixel_color( $coord[0], $coord[1] );
154
+ $colors[$position] = str_pad( $c['red'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['green'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['blue'], 3, '0', STR_PAD_LEFT ) . str_pad( $c['alpha'], 3, '0', STR_PAD_LEFT );
155
+ }
156
+
157
+ return max( $colors );
158
+
159
+ //return $colors;
160
+ }
161
+ }
162
+ }
includes/thumbs/default/class-foogallery-thumb-generator.php ADDED
@@ -0,0 +1,491 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class that performs all thumbnail generation within FooGallery
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Generator' ) ) {
6
+ class FooGallery_Thumb_Generator {
7
+
8
+ /**
9
+ * Array of resize arguments
10
+ *
11
+ * @var array
12
+ * @access private
13
+ */
14
+ private $args;
15
+
16
+ /**
17
+ * The file path to the original image
18
+ *
19
+ * @var string
20
+ * @access private
21
+ */
22
+ private $file_path;
23
+
24
+ /**
25
+ * The original image URL
26
+ *
27
+ * @var string
28
+ * @access private
29
+ */
30
+ private $image_url;
31
+
32
+ /**
33
+ * Any errors we encountered
34
+ *
35
+ * @var WP_Error
36
+ * @access private
37
+ */
38
+ private $error;
39
+
40
+ /**
41
+ * Is there an error
42
+ *
43
+ * @access public
44
+ * @return null
45
+ */
46
+ public function errored() {
47
+ return ! empty( $this->error );
48
+ }
49
+
50
+ /**
51
+ * Returns the error
52
+ *
53
+ * @access public
54
+ * @return null
55
+ */
56
+ public function error() {
57
+ return empty( $this->error ) ? null : $this->error;
58
+ }
59
+
60
+ /**
61
+ * Constructor to parse the args and determine cache folder
62
+ *
63
+ * @access public
64
+ *
65
+ * @param string $image_url
66
+ * @param array $args . (default: array())
67
+ */
68
+ public function __construct( $image_url, $args = array() ) {
69
+ $this->image_url = $image_url;
70
+
71
+ //converts URL's to paths if needed
72
+ $this->set_file_path( $image_url );
73
+
74
+ if ( $args ) {
75
+ $this->set_args( $args );
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Returns the base WordPress path
81
+ * @return string
82
+ */
83
+ private static function get_home_path() {
84
+ $url = str_replace( home_url(), '', site_url() );
85
+ $url = str_replace( $url, '', ABSPATH );
86
+ return $url;
87
+ }
88
+
89
+ /**
90
+ * Set the correct file path of the original image from the image URL
91
+ *
92
+ * @param string $image_url
93
+ */
94
+ public function set_file_path( $image_url ) {
95
+
96
+ //check if the $file_path is already a path within the site
97
+ if ( strpos( $image_url, self::get_home_path() ) === 0 ) {
98
+ $image_path = $image_url;
99
+ } else {
100
+ //we are dealing with a URL
101
+
102
+ $upload_dir = wp_upload_dir();
103
+
104
+ $base_url = set_url_scheme( $upload_dir['baseurl'] );
105
+
106
+ if ( strpos( $image_url, $base_url ) !== false ) {
107
+ //it's in the uploads folder
108
+ $image_path = str_replace( $base_url, $upload_dir['basedir'], $image_url );
109
+ } else {
110
+
111
+ $image_path = str_replace( trailingslashit( home_url() ), self::get_home_path(), $image_url );
112
+ }
113
+
114
+ //check if the file is local
115
+ if ( strpos( $image_url, trailingslashit( home_url() ) ) === 0 ) {
116
+ //strip all querystring params
117
+ $image_path = strtok( $image_path, '?' );
118
+
119
+ //check it exists
120
+ if ( ! file_exists( $image_path ) ) {
121
+ $this->error = new WP_Error( 'file-not-found' );
122
+ return;
123
+ }
124
+ }
125
+ }
126
+
127
+ $this->file_path = $image_path;
128
+ }
129
+
130
+ /**
131
+ * Parse the args and merge with defaults
132
+ *
133
+ * @param array $args
134
+ */
135
+ public function set_args( $args ) {
136
+
137
+ //these are the default arguments
138
+ $arg_defaults = apply_filters( 'foogallery_thumb_default_args', array(
139
+ 'width' => 0,
140
+ 'height' => 0,
141
+ 'crop' => false,
142
+ 'crop_from_position' => foogallery_get_setting( 'default_crop_position', FooGallery_Crop_Position::CROP_POSITION_DEFAULT ),
143
+ 'resize' => true,
144
+ 'watermark_options' => array(),
145
+ 'cache' => true,
146
+ 'skip_remote_check' => false, //not used. Only kept in to preserve the generated cache file name
147
+ 'default' => null,
148
+ 'jpeg_quality' => 90,
149
+ 'resize_animations' => true,
150
+ 'return' => 'url', //not used. Only kept in to preserve the generated cache file name
151
+ 'custom' => false, //not used. Only kept in to preserve the generated cache file name
152
+ 'background_fill' => null,
153
+ 'output_file' => false,
154
+ 'cache_with_query_params' => false //not used. Only kept in to preserve the generated cache file name
155
+ ) );
156
+
157
+ $args = wp_parse_args( $args, $arg_defaults );
158
+
159
+ // Cast some args
160
+ $args['crop'] = (bool) $args['crop'];
161
+ $args['resize'] = (bool) $args['resize'];
162
+ $args['cache'] = (bool) $args['cache'];
163
+ $args['width'] = (int) $args['width'];
164
+ $args['height'] = (int) $args['height'];
165
+
166
+ // Format the crop from position arg
167
+ if ( is_string( $args['crop_from_position'] ) && $args['crop_from_position'] ) {
168
+ $args['crop_from_position'] = explode( ',', $args['crop_from_position'] );
169
+ }
170
+
171
+ $this->args = apply_filters( 'foogallery_thumb_args', $args );
172
+ }
173
+
174
+ /**
175
+ * Get a specific arg
176
+ *
177
+ * @access public
178
+ *
179
+ * @param string $arg
180
+ * @return mixed
181
+ */
182
+ public function get_arg( $arg, $default = false ) {
183
+
184
+ if ( isset( $this->args[ $arg ] ) ) {
185
+ return $this->args[ $arg ];
186
+ }
187
+
188
+ return $default;
189
+ }
190
+
191
+ /**
192
+ * Get the full path to the cache file
193
+ *
194
+ * @access public
195
+ * @return string
196
+ */
197
+ public function get_cache_file_path() {
198
+ //check we have a path first
199
+ if ( ! $this->file_path ) {
200
+ return '';
201
+ }
202
+
203
+ $path = trailingslashit( $this->get_cache_file_directory() ) . $this->get_cache_filename();
204
+
205
+ return apply_filters( 'foogallery_thumb_cache_file_path', $path, $this );
206
+ }
207
+
208
+ /**
209
+ * Get the directory that the cache file should be saved too
210
+ *
211
+ * @return string
212
+ */
213
+ public function get_cache_file_directory() {
214
+ if ( $this->get_arg( 'output_file' ) ) {
215
+ return dirname( $this->get_arg( 'output_file' ) );
216
+ }
217
+
218
+ //check we have a path first
219
+ if ( ! $this->file_path ) {
220
+ return '';
221
+ }
222
+
223
+ //get a safe filename
224
+ $original_filename = basename( $this->file_path );
225
+ $parts = explode( '.', $original_filename );
226
+ array_pop( $parts );
227
+ $filename_nice = implode( '_', $parts );
228
+
229
+ $upload_dir = wp_upload_dir();
230
+
231
+ if ( strpos( $this->file_path, $upload_dir['basedir'] ) === 0 ) {
232
+
233
+ $sub_dir = dirname( str_replace( $upload_dir['basedir'], '', $this->file_path ) );
234
+ $new_dir = $upload_dir['basedir'] . '/cache' . trailingslashit( $sub_dir ) . $filename_nice;
235
+
236
+ } elseif ( strpos( $this->file_path, WP_CONTENT_DIR ) === 0 ) {
237
+
238
+ $sub_dir = dirname( str_replace( WP_CONTENT_DIR, '', $this->file_path ) );
239
+ $new_dir = $upload_dir['basedir'] . '/cache' . trailingslashit( $sub_dir ) . $filename_nice;
240
+
241
+ } elseif ( strpos( $this->file_path, self::get_home_path() ) === 0 ) {
242
+
243
+ $new_dir = $upload_dir['basedir'] . '/cache/local';
244
+
245
+ } else {
246
+
247
+ $parts = parse_url( $this->file_path );
248
+
249
+ if ( ! empty( $parts['host'] ) ) {
250
+ $new_dir = $upload_dir['basedir'] . '/cache/remote/' . sanitize_title( $parts['host'] );
251
+ } else {
252
+ $new_dir = $upload_dir['basedir'] . '/cache/remote';
253
+ }
254
+
255
+ }
256
+
257
+ $new_dir = str_replace( '/cache/cache', '/cache', $new_dir );
258
+
259
+ return $new_dir;
260
+ }
261
+
262
+ /**
263
+ * Get the filename of the cache file
264
+ *
265
+ * @return string
266
+ */
267
+ public function get_cache_filename() {
268
+ if ( $this->get_arg( 'output_file' ) ) {
269
+ return basename( $this->get_arg( 'output_file' ) );
270
+ }
271
+
272
+ //check we have a path first
273
+ if ( ! $this->file_path ) {
274
+ return '';
275
+ }
276
+
277
+ // Generate a short unique filename
278
+ $serialize = crc32( serialize( array_merge( $this->args, array( $this->file_path ) ) ) );
279
+
280
+ // Get the image extension
281
+ $ext = $this->get_image_extension();
282
+
283
+ // Gifs are converted to pngs
284
+ if ( $ext === 'gif' ) {
285
+ $ext = 'png';
286
+ }
287
+
288
+ return $serialize . '.' . $ext;
289
+ }
290
+
291
+ /**
292
+ * Get the extension of the original image
293
+ *
294
+ * @return string
295
+ */
296
+ public function get_image_extension() {
297
+
298
+ $filename = parse_url( $this->image_url, PHP_URL_PATH );
299
+
300
+ $ext = pathinfo( $filename, PATHINFO_EXTENSION );
301
+
302
+ if ( ! $ext ) {
303
+ // Seems like we dont have an ext, lets guess at JPG
304
+ $ext = 'jpg';
305
+ }
306
+
307
+ return strtolower( $ext );
308
+ }
309
+
310
+ /**
311
+ * Generates the thumbnail based on the args and returns the thumbnail URL
312
+ */
313
+ public function generate() {
314
+ $must_generate = !$this->get_arg( 'cache' );
315
+
316
+ if ( $must_generate || !file_exists( $this->get_cache_file_path() )) {
317
+ $this->generate_cache_file();
318
+ }
319
+
320
+ //if we had any errors then return the original
321
+ if ( $this->errored() ) {
322
+ return $this->image_url;
323
+ }
324
+
325
+ return $this->convert_path_to_url( $this->get_cache_file_path() );
326
+ }
327
+
328
+ /**
329
+ * Convert a path into a url
330
+ *
331
+ * @param string $path
332
+ * @return string url
333
+ */
334
+ private function convert_path_to_url( $path ) {
335
+
336
+ $upload_dir = wp_upload_dir();
337
+
338
+ if ( strpos( $path, $upload_dir['basedir'] ) !== false ) {
339
+ return str_replace( $upload_dir['basedir'], set_url_scheme( $upload_dir['baseurl'] ), $path );
340
+ } else {
341
+ return str_replace( self::get_home_path(), trailingslashit( home_url() ), $path );
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Generate the new cache file using the original image and args
347
+ *
348
+ * @return string new filepath
349
+ */
350
+ public function generate_cache_file() {
351
+
352
+ $new_filepath = $this->get_cache_file_path();
353
+ $file_path = $this->file_path;
354
+
355
+ // Up the php memory limit
356
+ @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', '256M' ) );
357
+
358
+ // Create the image
359
+ $editor = wp_get_image_editor( $file_path, array( 'methods' => array( 'get_image' ) ) );
360
+
361
+ if ( is_wp_error( $editor ) ) {
362
+ $this->error = $editor;
363
+ return;
364
+ }
365
+
366
+ wp_mkdir_p( $this->get_cache_file_directory() );
367
+
368
+ // Convert gif images to png before resizing
369
+ if ( $this->get_image_extension() === 'gif' ) {
370
+
371
+ // Save the converted image
372
+ $editor->save( $new_filepath, 'image/png' );
373
+
374
+ // Pass the new file back through the function so they are resized
375
+ $gif = new self( $new_filepath, array_merge( $this->args, array(
376
+ 'output_file' => $new_filepath,
377
+ 'cache' => false
378
+ ) ) );
379
+
380
+ $gif->generate();
381
+ return;
382
+ }
383
+
384
+ // Apply JPEG quality settings args
385
+ $editor->set_quality( $this->args['jpeg_quality'] );
386
+
387
+ apply_filters( 'foogallery_thumb_image_pre', $editor, $this->args );
388
+
389
+ //extract the values from args
390
+ $crop = $this->get_arg( 'crop', true );
391
+ $crop_from_position = $this->get_arg( 'crop_from_position', array( 'center', 'center' ) );
392
+ $width = $this->get_arg( 'width', 150 );
393
+ $height = $this->get_arg( 'height', 150 );
394
+ $resize = $this->get_arg( 'resize', true );
395
+
396
+ // Cropping
397
+ if ( $crop && $crop_from_position && $crop_from_position !== array( 'center', 'center' ) ) {
398
+ $this->crop_from_position( $editor, $width, $height, $crop_from_position, $resize );
399
+ } elseif ( $crop === true && $resize === true ) {
400
+ $editor->resize( $width, $height, true );
401
+ } elseif ( $crop === true && $resize === false ) {
402
+ $this->crop_from_center( $editor, $width, $height );
403
+ } else {
404
+ $editor->resize( $width, $height );
405
+ }
406
+
407
+ apply_filters( 'foogallery_thumb_image_post', $editor, $this->args );
408
+
409
+ $editor->save( $new_filepath );
410
+
411
+ do_action( 'foogallery_thumb_saved_cache_image', $this, $new_filepath );
412
+ }
413
+
414
+ /**
415
+ * Crop the image to the specified width and height from the centre of the image, no resize
416
+ *
417
+ * @param $editor
418
+ * @param $width
419
+ * @param $height
420
+ *
421
+ * @return mixed
422
+ */
423
+ private function crop_from_center( $editor, $width, $height ) {
424
+
425
+ $size = $editor->get_size();
426
+
427
+ $crop = array( 'x' => 0, 'y' => 0, 'width' => $size['width'], 'height' => $size['height'] );
428
+
429
+ if ( $width < $size['width'] ) {
430
+ $crop['x'] = intval( ( $size['width'] - $width ) / 2 );
431
+ $crop['width'] = $width;
432
+ }
433
+
434
+ if ( $height < $size['height'] ) {
435
+ $crop['y'] = intval( ( $size['height'] - $height ) / 2 );
436
+ $crop['height'] = $height;
437
+ }
438
+
439
+ return $editor->crop( $crop['x'], $crop['y'], $crop['width'], $crop['height'] );
440
+ }
441
+
442
+ /**
443
+ * Crop an image to the specified width and height from specific coordinates in the image
444
+ *
445
+ * @param $editor
446
+ * @param $width
447
+ * @param $height
448
+ * @param $position
449
+ * @param bool $resize
450
+ *
451
+ * @return mixed
452
+ */
453
+ private function crop_from_position( $editor, $width, $height, $position, $resize = true ) {
454
+
455
+ $size = $editor->get_size();
456
+
457
+ // resize to the largest dimension
458
+ if ( $resize ) {
459
+
460
+ $ratio1 = $size['width'] / $size['height'];
461
+ $ratio2 = $width / $height;
462
+
463
+ if ( $ratio1 < $ratio2 ) {
464
+ $_width = $width;
465
+ $_height = $width / $ratio1;
466
+ } else {
467
+ $_height = $height;
468
+ $_width = $height * $ratio1;
469
+ }
470
+
471
+ $editor->resize( $_width, $_height );
472
+ }
473
+
474
+ $size = $editor->get_size();
475
+ $crop = array( 'x' => 0, 'y' => 0 );
476
+
477
+ if ( $position[0] == 'right' )
478
+ $crop['x'] = absint( $size['width'] - $width );
479
+ else if ( $position[0] == 'center' )
480
+ $crop['x'] = intval( absint( $size['width'] - $width ) / 2 );
481
+
482
+ if ( $position[1] == 'bottom' )
483
+ $crop['y'] = absint( $size['height'] - $height );
484
+ else if ( $position[1] == 'center' )
485
+ $crop['y'] = intval( absint( $size['height'] - $height ) / 2 );
486
+
487
+
488
+ return $editor->crop( $crop['x'], $crop['y'], $width, $height );
489
+ }
490
+ }
491
+ }
includes/thumbs/default/class-foogallery-thumb-image-editor-gd.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FooGallery class that extends WP_Image_Editor_GD
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Image_Editor_GD' ) ) {
6
+ class FooGallery_Thumb_Image_Editor_GD extends WP_Image_Editor_GD {
7
+
8
+ public function get_image() {
9
+ return $this->image;
10
+ }
11
+
12
+ public function update_image( $image ) {
13
+ $this->image = $image;
14
+ }
15
+
16
+ public function update_size( $width = null, $height = null ) {
17
+ return parent::update_size( $width, $height );
18
+ }
19
+
20
+ public static function supports_mime_type( $mime_type ) {
21
+ $image_types = imagetypes();
22
+ switch( $mime_type ) {
23
+ case 'image/jpeg':
24
+ case 'image/jpg':
25
+ return ($image_types & IMG_JPG) != 0;
26
+ case 'image/png':
27
+ return ($image_types & IMG_PNG) != 0;
28
+ case 'image/gif':
29
+ return ($image_types & IMG_GIF) != 0;
30
+ }
31
+
32
+ return false;
33
+ }
34
+
35
+ /**
36
+ * Get the color at a specific coordinate
37
+ *
38
+ * @param $x
39
+ * @param $y
40
+ *
41
+ * @return object
42
+ */
43
+ public function get_pixel_color($x, $y) {
44
+ $rgba = imagecolorat($this->image, $x, $y);
45
+ $color = imagecolorsforindex($this->image, $rgba);
46
+
47
+ return $color;
48
+ }
49
+ }
50
+ }
includes/thumbs/default/class-foogallery-thumb-image-editor-imagick.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * FooGallery class that extends WP_Image_Editor_Imagick
4
+ */
5
+ if ( ! class_exists( 'FooGallery_Thumb_Image_Editor_Imagick' ) ) {
6
+ class FooGallery_Thumb_Image_Editor_Imagick extends WP_Image_Editor_Imagick {
7
+
8
+ public function get_image() {
9
+ return $this->image;
10
+ }
11
+
12
+ public function update_image( $image ) {
13
+ $this->image = $image;
14
+ }
15
+
16
+ public function update_size( $width = null, $height = null ) {
17
+ return parent::update_size( $width, $height );
18
+ }
19
+
20
+ /**
21
+ * Get the color at a specific coordinate
22
+ *
23
+ * @param $x
24
+ * @param $y
25
+ *
26
+ * @return object
27
+ */
28
+ public function get_pixel_color($x, $y) {
29
+ $pixel = $this->image->getImagePixelColor($x, $y);
30
+
31
+ // Un-normalized values don't give a full range 0-1 alpha channel
32
+ // So we ask for normalized values, and then we un-normalize it ourselves.
33
+ $colorArray = $pixel->getColor(true);
34
+
35
+ $color = array(
36
+ 'red' => (int) round($colorArray['r'] * 255),
37
+ 'green' => (int) round($colorArray['g'] * 255),
38
+ 'blue' => (int) round($colorArray['b'] * 255),
39
+ 'alpha' => (int) (127 - round($colorArray['a'] * 127))
40
+ );
41
+
42
+ return $color;
43
+ }
44
+ }
45
+ }
includes/thumbs/default/tests/test1.png ADDED
Binary file
includes/thumbs/default/tests/test2.png ADDED
Binary file
includes/thumbs/default/tests/test3 ADDED
Binary file
includes/thumbs/default/tests/test4.gif ADDED
Binary file
includes/thumbs/default/tests/test5.jpg ADDED
Binary file
includes/thumbs/default/tests/test6.bmp ADDED
Binary file
includes/thumbs/dummy/class-foogallery-thumb-engine-dummy.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for the dummy thumbnail engine in FooGallery
5
+ */
6
+ if ( ! class_exists( 'FooGallery_Thumb_Engine_Dummy' ) ) {
7
+
8
+ class FooGallery_Thumb_Engine_Dummy extends FooGallery_Thumb_Engine {
9
+
10
+ /**
11
+ * Do nothing on init
12
+ */
13
+ function init() {
14
+ //do nothing
15
+ }
16
+
17
+ /**
18
+ * Generate the dummyimage.com thumbnail URL
19
+ * @param $url
20
+ * @param array $args
21
+ *
22
+ * @return string
23
+ */
24
+ function generate( $url, $args = array() ) {
25
+ $width = (int) $args['width'];
26
+ $height = (int) $args['height'];
27
+ $attachment_id = (int) $args['foogallery_attachment_id'];
28
+ $colors = array(
29
+ array( 'background' => '000000', 'text' => 'ffffff' ),
30
+ array( 'background' => '001eff', 'text' => 'ffffff' ),
31
+ array( 'background' => '5400ff', 'text' => 'ffffff' ),
32
+ array( 'background' => '4c1616', 'text' => 'ffffff' ),
33
+ array( 'background' => '663e00', 'text' => 'ffffff' ),
34
+ array( 'background' => '376600', 'text' => 'ffffff' ),
35
+ array( 'background' => '00663e', 'text' => 'ffffff' ),
36
+ array( 'background' => '006566', 'text' => 'ffffff' ),
37
+ array( 'background' => '003c66', 'text' => 'ffffff' ),
38
+ array( 'background' => '290066', 'text' => 'ffffff' ),
39
+ array( 'background' => '660062', 'text' => 'ffffff' ),
40
+ array( 'background' => '66000e', 'text' => 'ffffff' ),
41
+ array( 'background' => 'cccccc', 'text' => '000000' ),
42
+ array( 'background' => 'ff0000', 'text' => '000000' ),
43
+ array( 'background' => 'ff6c00', 'text' => '000000' ),
44
+ array( 'background' => 'ffe400', 'text' => '000000' ),
45
+ array( 'background' => '66ff00', 'text' => '000000' ),
46
+ array( 'background' => '00fcff', 'text' => '000000' ),
47
+ array( 'background' => 'f000ff', 'text' => '000000' ),
48
+ array( 'background' => 'dc7f8c', 'text' => '000000' ),
49
+ array( 'background' => 'db7fdc', 'text' => '000000' ),
50
+ array( 'background' => '7f81dc', 'text' => '000000' ),
51
+ array( 'background' => '7fdbdc', 'text' => '000000' ),
52
+ array( 'background' => '7fdca6', 'text' => '000000' ),
53
+ array( 'background' => 'b8dc7f', 'text' => '000000' ),
54
+ array( 'background' => 'dcd07f', 'text' => '000000' ),
55
+ array( 'background' => 'dc8a7f', 'text' => '000000' )
56
+ );
57
+
58
+ $color = $colors[ array_rand( $colors ) ];
59
+
60
+ return sprintf( 'https://dummyimage.com/%dx%d/%s/%s&text=Item+%s+(%s×%s)',
61
+ $width, $height, $color['background'], $color['text'], $attachment_id, $width, $height );
62
+ }
63
+
64
+ function clear_local_cache_for_file( $file ) {
65
+ return; //do nothing
66
+ }
67
+
68
+ function has_local_cache() {
69
+ return false;
70
+ }
71
+
72
+ function get_last_error() {
73
+ return null;
74
+ }
75
+ }
76
+ }
77
+
78
+ //example : https://dummyimage.com/1920x1200/b8dc7f/000000&text=Item+0+(1920x720)
includes/thumbs/includes.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //include the base engine class
4
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/class-foogallery-thumb-engine.php' );
5
+
6
+ //include the manager class
7
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/class-foogallery-thumb-manager.php' );
8
+
9
+ //include files for default engine
10
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/default/class-foogallery-thumb-engine-default.php' );
11
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/default/class-foogallery-thumb-generator.php' );
12
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/default/class-foogallery-thumb-generator-background-fill.php' );
13
+
14
+ //include files for dummy engine
15
+ require_once( FOOGALLERY_PATH . 'includes/thumbs/dummy/class-foogallery-thumb-engine-dummy.php' );
includes/thumbs/shortpixel/class-foogallery-thumb-engine-shortpixel.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for the shortpixel adaptive image thumbnails. Coming Soon!
5
+ */
6
+ if ( ! class_exists( 'FooGallery_Thumb_Engine_Shortpixel' ) ) {
7
+
8
+ class FooGallery_Thumb_Engine_Shortpixel extends FooGallery_Thumb_Engine {
9
+
10
+ }
11
+ }
js/foogallery.admin.min.js CHANGED
@@ -1,9 +1,9 @@
1
- /*
2
- * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
- * @version 1.4.26
4
- * @link
5
- * @copyright Steven Usher & Brad Vincent 2015
6
- * @license Released under the GPLv3 license.
7
- */
8
-
9
  !function(a,b,c,d,e){b.Settings=c.Class.extend({construct:function(c,f){var g=this;g.$el=d.jq(c)?c:a(c),g.opt=e.extend({},b.Settings.defaults,f),g.mqlMobile=window.matchMedia("(max-width: "+g.opt.mobile+"px)"),g.isMobile=g.mqlMobile.matches,g.mqlHover=window.matchMedia("(hover: hover)"),g.canHover=g.mqlHover.matches,g.tabs=new b.Settings.VerticalTabs(g),g.onMqlMobileChanged=g.onMqlMobileChanged.bind(g),g.onMqlHoverChanged=g.onMqlHoverChanged.bind(g)},init:function(){var a=this;a.tabs.init(),a.isMobile&&a.setupMobile(),a.canHover&&a.setupHover(),a.mqlMobile.addListener(a.onMqlMobileChanged),a.mqlHover.addListener(a.onMqlHoverChanged)},destroy:function(){var a=this;a.tabs.destroy(),a.mqlMobile.removeListener(a.onMqlMobileChanged),a.mqlMobile.removeListener(a.onMqlHoverChanged)},setupMobile:function(){var a=this;a.$el.addClass("is-mobile"),a.tabs.setupMobile()},teardownMobile:function(){var a=this;a.$el.removeClass("is-mobile"),a.tabs.teardownMobile()},setupHover:function(){var a=this;a.$el.addClass("can-hover"),a.tabs.setupHover()},teardownHover:function(){var a=this;a.$el.removeClass("can-hover"),a.tabs.teardownHover()},onMqlMobileChanged:function(a){var b=this;(b.isMobile=a.matches)?b.setupMobile():b.teardownMobile()},onMqlHoverChanged:function(a){var b=this;(b.canHover=a.matches)?b.setupHover():b.teardownHover()}}),b.Settings.defaults={mobile:960},a(function(){b.settings=new b.Settings(".foogallery-settings",{mobile:960}),b.settings.init()})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){b.Settings.VerticalTabs=c.Class.extend({construct:function(a){var b=this;b.settings=a,b.$tabs=null,b.$contents=null,b.children=[]},init:function(){var a=this,c=a.settings.$el;a.$tabs=c.children(".foogallery-vertical-tabs"),a.$contents=c.children(".foogallery-tab-contents"),a.children=a.$tabs.children(".foogallery-vertical-tab").map(function(c,d){var e=new b.Settings.VerticalTabs.Tab(a,d);return e.init(),e}).get()},destroy:function(){this.children.forEach(function(a){a.destroy()})},setupMobile:function(){this.children.forEach(function(a){a.setupMobile()})},teardownMobile:function(){this.children.forEach(function(a){a.teardownMobile()})},setupHover:function(){this.children.forEach(function(a){a.setupHover()})},teardownHover:function(){this.children.forEach(function(a){a.teardownHover()})},hideMenu:function(){this.children.forEach(function(a){a.toggleMenu(!1)})},showMenu:function(a){this.children.forEach(function(b){b.toggleMenu(b.name===a)})}}),b.Settings.VerticalTabs.Tab=c.Class.extend({construct:function(b,c){var e=this;e.vt=b,e.$el=d.jq(c)?c:a(c),e.name=null,e.selector=null,e.$content=null,e.$tabs=null,e.$header=null,e.children=[],e.target=null,e.hasChildren=!1,e._enter=null,e._leave=null,e.onClick=e.onClick.bind(e),e.onDocumentClick=e.onDocumentClick.bind(e),e.onMouseEnter=e.onMouseEnter.bind(e),e.onMouseLeave=e.onMouseLeave.bind(e)},init:function(){var c=this;c.name=c.$el.data("name"),c.selector='[data-name="'+c.name+'"]',c.$content=c.vt.$contents.find(c.selector),c.$tabs=c.$el.children(".foogallery-vertical-child-tabs"),c.children=c.$tabs.children(".foogallery-vertical-child-tab").map(function(a,d){var e=new b.Settings.VerticalTabs.Tab(c.vt,d);return e.init(),e}).get(),c.hasChildren=c.children.length>0,c.target=c.children.find(function(a){return a.name===c.name})||null,c.$header=a("<div/>",{class:"foogallery-vertical-child-header"}).append(a("<span/>",{class:"foogallery-tab-text",text:c.$el.children(".foogallery-tab-text").first().text()})),c.$el.on("click",c.onClick)},destroy:function(){var a=this;a.$el.off("click",a.onClick)},setupMobile:function(){var a=this;a.$tabs.prepend(a.$header)},teardownMobile:function(){this.$header.remove()},setupHover:function(){var a=this;a.$el.on({mouseenter:a.onMouseEnter,mouseleave:a.onMouseLeave})},teardownHover:function(){var a=this;a.$el.off({mouseenter:a.onMouseEnter,mouseleave:a.onMouseLeave})},activate:function(){var a=this;if(a.target instanceof b.Settings.VerticalTabs.Tab)a.target.activate();else{a.vt.$tabs.add(a.vt.$contents).find(".foogallery-tab-active").removeClass("foogallery-tab-active");a.$el.closest(".foogallery-vertical-tab").add(a.$el).add(a.$content).addClass("foogallery-tab-active"),a.vt.hideMenu()}},toggleMenu:function(b){var c=this,e=c.$el.closest(".foogallery-vertical-tab");b=d.undef(b)?!e.hasClass("foogallery-show-child-menu"):!!b,e.toggleClass("foogallery-show-child-menu",b),b?a(document).on("click",c.onDocumentClick):a(document).off("click",c.onDocumentClick)},onMouseEnter:function(a){var b=this;b.hasChildren&&(clearTimeout(b._leave),b._leave=null,null===b._enter&&(b._enter=setTimeout(function(){b.$el.addClass("foogallery-show-child-menu"),b._enter=null},300)))},onMouseLeave:function(a){var b=this;b.hasChildren&&(clearTimeout(b._enter),b._enter=null,null===b._leave&&(b._leave=setTimeout(function(){b.$el.removeClass("foogallery-show-child-menu"),b._leave=null},300)))},onClick:function(a){a.preventDefault(),a.stopPropagation();var b=this;b.hasChildren&&b.vt.settings.isMobile&&!b.vt.settings.canHover?b.toggleMenu():b.activate()},onDocumentClick:function(a){a.preventDefault(),this.toggleMenu(!1)}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj);
1
+ /*
2
+ * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
+ * @version 1.4.26
4
+ * @link
5
+ * @copyright Steven Usher & Brad Vincent 2015
6
+ * @license Released under the GPLv3 license.
7
+ */
8
+
9
  !function(a,b,c,d,e){b.Settings=c.Class.extend({construct:function(c,f){var g=this;g.$el=d.jq(c)?c:a(c),g.opt=e.extend({},b.Settings.defaults,f),g.mqlMobile=window.matchMedia("(max-width: "+g.opt.mobile+"px)"),g.isMobile=g.mqlMobile.matches,g.mqlHover=window.matchMedia("(hover: hover)"),g.canHover=g.mqlHover.matches,g.tabs=new b.Settings.VerticalTabs(g),g.onMqlMobileChanged=g.onMqlMobileChanged.bind(g),g.onMqlHoverChanged=g.onMqlHoverChanged.bind(g)},init:function(){var a=this;a.tabs.init(),a.isMobile&&a.setupMobile(),a.canHover&&a.setupHover(),a.mqlMobile.addListener(a.onMqlMobileChanged),a.mqlHover.addListener(a.onMqlHoverChanged)},destroy:function(){var a=this;a.tabs.destroy(),a.mqlMobile.removeListener(a.onMqlMobileChanged),a.mqlMobile.removeListener(a.onMqlHoverChanged)},setupMobile:function(){var a=this;a.$el.addClass("is-mobile"),a.tabs.setupMobile()},teardownMobile:function(){var a=this;a.$el.removeClass("is-mobile"),a.tabs.teardownMobile()},setupHover:function(){var a=this;a.$el.addClass("can-hover"),a.tabs.setupHover()},teardownHover:function(){var a=this;a.$el.removeClass("can-hover"),a.tabs.teardownHover()},onMqlMobileChanged:function(a){var b=this;(b.isMobile=a.matches)?b.setupMobile():b.teardownMobile()},onMqlHoverChanged:function(a){var b=this;(b.canHover=a.matches)?b.setupHover():b.teardownHover()}}),b.Settings.defaults={mobile:960},a(function(){b.settings=new b.Settings(".foogallery-settings",{mobile:960}),b.settings.init()})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){b.Settings.VerticalTabs=c.Class.extend({construct:function(a){var b=this;b.settings=a,b.$tabs=null,b.$contents=null,b.children=[]},init:function(){var a=this,c=a.settings.$el;a.$tabs=c.children(".foogallery-vertical-tabs"),a.$contents=c.children(".foogallery-tab-contents"),a.children=a.$tabs.children(".foogallery-vertical-tab").map(function(c,d){var e=new b.Settings.VerticalTabs.Tab(a,d);return e.init(),e}).get()},destroy:function(){this.children.forEach(function(a){a.destroy()})},setupMobile:function(){this.children.forEach(function(a){a.setupMobile()})},teardownMobile:function(){this.children.forEach(function(a){a.teardownMobile()})},setupHover:function(){this.children.forEach(function(a){a.setupHover()})},teardownHover:function(){this.children.forEach(function(a){a.teardownHover()})},hideMenu:function(){this.children.forEach(function(a){a.toggleMenu(!1)})},showMenu:function(a){this.children.forEach(function(b){b.toggleMenu(b.name===a)})}}),b.Settings.VerticalTabs.Tab=c.Class.extend({construct:function(b,c){var e=this;e.vt=b,e.$el=d.jq(c)?c:a(c),e.name=null,e.selector=null,e.$content=null,e.$tabs=null,e.$header=null,e.children=[],e.target=null,e.hasChildren=!1,e._enter=null,e._leave=null,e.onClick=e.onClick.bind(e),e.onDocumentClick=e.onDocumentClick.bind(e),e.onMouseEnter=e.onMouseEnter.bind(e),e.onMouseLeave=e.onMouseLeave.bind(e)},init:function(){var c=this;c.name=c.$el.data("name"),c.selector='[data-name="'+c.name+'"]',c.$content=c.vt.$contents.find(c.selector),c.$tabs=c.$el.children(".foogallery-vertical-child-tabs"),c.children=c.$tabs.children(".foogallery-vertical-child-tab").map(function(a,d){var e=new b.Settings.VerticalTabs.Tab(c.vt,d);return e.init(),e}).get(),c.hasChildren=c.children.length>0,c.target=c.children.find(function(a){return a.name===c.name})||null,c.$header=a("<div/>",{class:"foogallery-vertical-child-header"}).append(a("<span/>",{class:"foogallery-tab-text",text:c.$el.children(".foogallery-tab-text").first().text()})),c.$el.on("click",c.onClick)},destroy:function(){var a=this;a.$el.off("click",a.onClick)},setupMobile:function(){var a=this;a.$tabs.prepend(a.$header)},teardownMobile:function(){this.$header.remove()},setupHover:function(){var a=this;a.$el.on({mouseenter:a.onMouseEnter,mouseleave:a.onMouseLeave})},teardownHover:function(){var a=this;a.$el.off({mouseenter:a.onMouseEnter,mouseleave:a.onMouseLeave})},activate:function(){var a=this;if(a.target instanceof b.Settings.VerticalTabs.Tab)a.target.activate();else{a.vt.$tabs.add(a.vt.$contents).find(".foogallery-tab-active").removeClass("foogallery-tab-active");a.$el.closest(".foogallery-vertical-tab").add(a.$el).add(a.$content).addClass("foogallery-tab-active"),a.vt.hideMenu()}},toggleMenu:function(b){var c=this,e=c.$el.closest(".foogallery-vertical-tab");b=d.undef(b)?!e.hasClass("foogallery-show-child-menu"):!!b,e.toggleClass("foogallery-show-child-menu",b),b?a(document).on("click",c.onDocumentClick):a(document).off("click",c.onDocumentClick)},onMouseEnter:function(a){var b=this;b.hasChildren&&(clearTimeout(b._leave),b._leave=null,null===b._enter&&(b._enter=setTimeout(function(){b.$el.addClass("foogallery-show-child-menu"),b._enter=null},300)))},onMouseLeave:function(a){var b=this;b.hasChildren&&(clearTimeout(b._enter),b._enter=null,null===b._leave&&(b._leave=setTimeout(function(){b.$el.removeClass("foogallery-show-child-menu"),b._leave=null},300)))},onClick:function(a){a.preventDefault(),a.stopPropagation();var b=this;b.hasChildren&&b.vt.settings.isMobile&&!b.vt.settings.canHover?b.toggleMenu():b.activate()},onDocumentClick:function(a){a.preventDefault(),this.toggleMenu(!1)}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj);